Auto merge of #51944 - MajorBreakfast:generic-future-obj, r=cramertj
Make custom trait object for `Future` generic - `TaskObj` -> `FutureObj<'static, ()>` - The `impl From<...> for FutureObj<'a, T>` impls are impossible because of the type parameter `T`. The impl has to live in libstd, but `FutureObj<'a, T>` is from libcore. Therefore `Into<FutureObj<'a, T>>` was implemented instead. Edit: This didn‘t compile without warnings. I am now using non-generic Form impls. See https://github.com/rust-lang-nursery/futures-rs/issues/1058 r? @cramertj Edit: Added lifetime
This commit is contained in:
commit
c8df60a146
@ -58,16 +58,16 @@
|
||||
use core::any::Any;
|
||||
use core::borrow;
|
||||
use core::cmp::Ordering;
|
||||
use core::convert::From;
|
||||
use core::fmt;
|
||||
use core::future::Future;
|
||||
use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj};
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::FusedIterator;
|
||||
use core::marker::{Unpin, Unsize};
|
||||
use core::mem::{self, PinMut};
|
||||
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
|
||||
use core::ptr::{self, NonNull, Unique};
|
||||
use core::task::{Context, Poll, UnsafeTask, TaskObj, LocalTaskObj};
|
||||
use core::convert::From;
|
||||
use core::task::{Context, Poll};
|
||||
|
||||
use raw_vec::RawVec;
|
||||
use str::from_boxed_utf8_unchecked;
|
||||
@ -915,7 +915,7 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}
|
||||
impl<T: ?Sized> Unpin for PinBox<T> {}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
impl<'a, F: ?Sized + Future + Unpin> Future for Box<F> {
|
||||
impl<F: ?Sized + Future + Unpin> Future for Box<F> {
|
||||
type Output = F::Output;
|
||||
|
||||
fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
@ -924,7 +924,7 @@ impl<'a, F: ?Sized + Future + Unpin> Future for Box<F> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
impl<'a, F: ?Sized + Future> Future for PinBox<F> {
|
||||
impl<F: ?Sized + Future> Future for PinBox<F> {
|
||||
type Output = F::Output;
|
||||
|
||||
fn poll(mut self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||
@ -933,46 +933,67 @@ impl<'a, F: ?Sized + Future> Future for PinBox<F> {
|
||||
}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
unsafe impl<F: Future<Output = ()> + 'static> UnsafeTask for PinBox<F> {
|
||||
unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F>
|
||||
where F: Future<Output = T> + 'a
|
||||
{
|
||||
fn into_raw(self) -> *mut () {
|
||||
PinBox::into_raw(self) as *mut ()
|
||||
Box::into_raw(self) as *mut ()
|
||||
}
|
||||
|
||||
unsafe fn poll(task: *mut (), cx: &mut Context) -> Poll<()> {
|
||||
let ptr = task as *mut F;
|
||||
unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
|
||||
let ptr = ptr as *mut F;
|
||||
let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr);
|
||||
pin.poll(cx)
|
||||
}
|
||||
|
||||
unsafe fn drop(task: *mut ()) {
|
||||
drop(PinBox::from_raw(task as *mut F))
|
||||
unsafe fn drop(ptr: *mut ()) {
|
||||
drop(Box::from_raw(ptr as *mut F))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
impl<F: Future<Output = ()> + Send + 'static> From<PinBox<F>> for TaskObj {
|
||||
unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinBox<F>
|
||||
where F: Future<Output = T> + 'a
|
||||
{
|
||||
fn into_raw(self) -> *mut () {
|
||||
PinBox::into_raw(self) as *mut ()
|
||||
}
|
||||
|
||||
unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
|
||||
let ptr = ptr as *mut F;
|
||||
let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr);
|
||||
pin.poll(cx)
|
||||
}
|
||||
|
||||
unsafe fn drop(ptr: *mut ()) {
|
||||
drop(PinBox::from_raw(ptr as *mut F))
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
impl<'a, F: Future<Output = ()> + Send + 'a> From<PinBox<F>> for FutureObj<'a, ()> {
|
||||
fn from(boxed: PinBox<F>) -> Self {
|
||||
TaskObj::new(boxed)
|
||||
FutureObj::new(boxed)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
impl<F: Future<Output = ()> + Send + 'static> From<Box<F>> for TaskObj {
|
||||
impl<'a, F: Future<Output = ()> + Send + 'a> From<Box<F>> for FutureObj<'a, ()> {
|
||||
fn from(boxed: Box<F>) -> Self {
|
||||
TaskObj::new(PinBox::from(boxed))
|
||||
FutureObj::new(boxed)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
impl<F: Future<Output = ()> + 'static> From<PinBox<F>> for LocalTaskObj {
|
||||
impl<'a, F: Future<Output = ()> + 'a> From<PinBox<F>> for LocalFutureObj<'a, ()> {
|
||||
fn from(boxed: PinBox<F>) -> Self {
|
||||
LocalTaskObj::new(boxed)
|
||||
LocalFutureObj::new(boxed)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
impl<F: Future<Output = ()> + 'static> From<Box<F>> for LocalTaskObj {
|
||||
impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> {
|
||||
fn from(boxed: Box<F>) -> Self {
|
||||
LocalTaskObj::new(PinBox::from(boxed))
|
||||
LocalFutureObj::new(boxed)
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,6 @@
|
||||
reason = "futures in libcore are unstable",
|
||||
issue = "50547")]
|
||||
|
||||
//! Asynchronous values.
|
||||
|
||||
use mem::PinMut;
|
||||
use marker::Unpin;
|
||||
use task::{self, Poll};
|
179
src/libcore/future/future_obj.rs
Normal file
179
src/libcore/future/future_obj.rs
Normal file
@ -0,0 +1,179 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<dyn Future<Output = T> + 'a>`.
|
||||
///
|
||||
/// This custom trait object was introduced for two reasons:
|
||||
/// - Currently it is not possible to take `dyn Trait` by value and
|
||||
/// `Box<dyn Trait>` 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<T>,
|
||||
drop_fn: unsafe fn(*mut ()),
|
||||
_marker: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
impl<'a, T> LocalFutureObj<'a, T> {
|
||||
/// Create a `LocalFutureObj` from a custom trait object representation.
|
||||
#[inline]
|
||||
pub fn new<F: UnsafeFutureObj<'a, T> + '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<FutureObj<'a, T>> 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<Self>, cx: &mut Context) -> Poll<T> {
|
||||
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<dyn Future<Output = T> + Send + 'a>`.
|
||||
///
|
||||
/// This custom trait object was introduced for two reasons:
|
||||
/// - Currently it is not possible to take `dyn Trait` by value and
|
||||
/// `Box<dyn Trait>` 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>);
|
||||
|
||||
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<F: UnsafeFutureObj<'a, T> + 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<Self>, cx: &mut Context) -> Poll<T> {
|
||||
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<T>;
|
||||
|
||||
/// 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<Output = T> + Unpin + 'a
|
||||
{
|
||||
fn into_raw(self) -> *mut () {
|
||||
self as *mut F as *mut ()
|
||||
}
|
||||
|
||||
unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
|
||||
PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx)
|
||||
}
|
||||
|
||||
unsafe fn drop(_ptr: *mut ()) {}
|
||||
}
|
21
src/libcore/future/mod.rs
Normal file
21
src/libcore/future/mod.rs
Normal file
@ -0,0 +1,21 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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")]
|
||||
|
||||
//! Asynchronous values.
|
||||
|
||||
mod future;
|
||||
pub use self::future::Future;
|
||||
|
||||
mod future_obj;
|
||||
pub use self::future_obj::{FutureObj, LocalFutureObj, UnsafeFutureObj};
|
@ -18,10 +18,12 @@
|
||||
use clone;
|
||||
use cmp;
|
||||
use fmt;
|
||||
use future::{Future, UnsafeFutureObj};
|
||||
use hash;
|
||||
use intrinsics;
|
||||
use marker::{Copy, PhantomData, Sized, Unpin, Unsize};
|
||||
use ptr;
|
||||
use task::{Context, Poll};
|
||||
use ops::{Deref, DerefMut, CoerceUnsized};
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -1227,3 +1229,18 @@ impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinMut<'a, U>> for PinM
|
||||
|
||||
#[unstable(feature = "pin", issue = "49150")]
|
||||
impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {}
|
||||
|
||||
#[unstable(feature = "futures_api", issue = "50547")]
|
||||
unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for PinMut<'a, F>
|
||||
where F: Future<Output = T> + 'a
|
||||
{
|
||||
fn into_raw(self) -> *mut () {
|
||||
unsafe { PinMut::get_mut_unchecked(self) as *mut F as *mut () }
|
||||
}
|
||||
|
||||
unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
|
||||
PinMut::new_unchecked(&mut *(ptr as *mut F)).poll(cx)
|
||||
}
|
||||
|
||||
unsafe fn drop(_ptr: *mut ()) {}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
issue = "50547")]
|
||||
|
||||
use fmt;
|
||||
use super::{TaskObj, LocalTaskObj};
|
||||
use future::{FutureObj, LocalFutureObj};
|
||||
|
||||
/// A task executor.
|
||||
///
|
||||
@ -29,7 +29,7 @@ pub trait Executor {
|
||||
///
|
||||
/// The executor may be unable to spawn tasks, either because it has
|
||||
/// been shut down or is resource-constrained.
|
||||
fn spawn_obj(&mut self, task: TaskObj) -> Result<(), SpawnObjError>;
|
||||
fn spawn_obj(&mut self, task: FutureObj<'static, ()>) -> Result<(), SpawnObjError>;
|
||||
|
||||
/// Determine whether the executor is able to spawn new tasks.
|
||||
///
|
||||
@ -76,7 +76,7 @@ pub struct SpawnObjError {
|
||||
pub kind: SpawnErrorKind,
|
||||
|
||||
/// The task for which spawning was attempted
|
||||
pub task: TaskObj,
|
||||
pub task: FutureObj<'static, ()>,
|
||||
}
|
||||
|
||||
/// The result of a failed spawn
|
||||
@ -86,5 +86,5 @@ pub struct SpawnLocalObjError {
|
||||
pub kind: SpawnErrorKind,
|
||||
|
||||
/// The task for which spawning was attempted
|
||||
pub task: LocalTaskObj,
|
||||
pub task: LocalFutureObj<'static, ()>,
|
||||
}
|
||||
|
@ -25,8 +25,5 @@ pub use self::executor::{
|
||||
mod poll;
|
||||
pub use self::poll::Poll;
|
||||
|
||||
mod task;
|
||||
pub use self::task::{TaskObj, LocalTaskObj, UnsafeTask};
|
||||
|
||||
mod wake;
|
||||
pub use self::wake::{Waker, LocalWaker, UnsafeWake};
|
||||
|
@ -1,142 +0,0 @@
|
||||
// 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 mem::PinMut;
|
||||
use super::{Context, Poll};
|
||||
|
||||
/// A custom trait object for polling tasks, roughly akin to
|
||||
/// `Box<Future<Output = ()>>`.
|
||||
/// Contrary to `TaskObj`, `LocalTaskObj` does not have a `Send` bound.
|
||||
pub struct LocalTaskObj {
|
||||
ptr: *mut (),
|
||||
poll_fn: unsafe fn(*mut (), &mut Context) -> Poll<()>,
|
||||
drop_fn: unsafe fn(*mut ()),
|
||||
}
|
||||
|
||||
impl LocalTaskObj {
|
||||
/// Create a `LocalTaskObj` from a custom trait object representation.
|
||||
#[inline]
|
||||
pub fn new<T: UnsafeTask>(t: T) -> LocalTaskObj {
|
||||
LocalTaskObj {
|
||||
ptr: t.into_raw(),
|
||||
poll_fn: T::poll,
|
||||
drop_fn: T::drop,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the `LocalTaskObj` into a `TaskObj`
|
||||
/// To make this operation safe one has to ensure that the `UnsafeTask`
|
||||
/// instance from which this `LocalTaskObj` was created actually implements
|
||||
/// `Send`.
|
||||
pub unsafe fn as_task_obj(self) -> TaskObj {
|
||||
TaskObj(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for LocalTaskObj {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("LocalTaskObj")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TaskObj> for LocalTaskObj {
|
||||
fn from(task: TaskObj) -> LocalTaskObj {
|
||||
task.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Future for LocalTaskObj {
|
||||
type Output = ();
|
||||
|
||||
#[inline]
|
||||
fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<()> {
|
||||
unsafe {
|
||||
(self.poll_fn)(self.ptr, cx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for LocalTaskObj {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
(self.drop_fn)(self.ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A custom trait object for polling tasks, roughly akin to
|
||||
/// `Box<Future<Output = ()> + Send>`.
|
||||
pub struct TaskObj(LocalTaskObj);
|
||||
|
||||
unsafe impl Send for TaskObj {}
|
||||
|
||||
impl TaskObj {
|
||||
/// Create a `TaskObj` from a custom trait object representation.
|
||||
#[inline]
|
||||
pub fn new<T: UnsafeTask + Send>(t: T) -> TaskObj {
|
||||
TaskObj(LocalTaskObj::new(t))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for TaskObj {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("TaskObj")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Future for TaskObj {
|
||||
type Output = ();
|
||||
|
||||
#[inline]
|
||||
fn poll(self: PinMut<Self>, 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 task trait object for `TaskObj`, 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 UnsafeTask: 'static {
|
||||
/// Convert a owned instance into a (conceptually owned) void pointer.
|
||||
fn into_raw(self) -> *mut ();
|
||||
|
||||
/// Poll the task 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(task: *mut (), cx: &mut Context) -> Poll<()>;
|
||||
|
||||
/// Drops the task 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(task: *mut ());
|
||||
}
|
@ -19,9 +19,10 @@ use std::sync::{
|
||||
Arc,
|
||||
atomic::{self, AtomicUsize},
|
||||
};
|
||||
use std::future::FutureObj;
|
||||
use std::task::{
|
||||
Context, Poll, Wake,
|
||||
Executor, TaskObj, SpawnObjError,
|
||||
Executor, SpawnObjError,
|
||||
local_waker_from_nonlocal,
|
||||
};
|
||||
|
||||
@ -37,7 +38,7 @@ impl Wake for Counter {
|
||||
|
||||
struct NoopExecutor;
|
||||
impl Executor for NoopExecutor {
|
||||
fn spawn_obj(&mut self, _: TaskObj) -> Result<(), SpawnObjError> {
|
||||
fn spawn_obj(&mut self, _: FutureObj<'static, ()>) -> Result<(), SpawnObjError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -19,10 +19,11 @@ use std::sync::{
|
||||
Arc,
|
||||
atomic::{self, AtomicUsize},
|
||||
};
|
||||
use std::future::FutureObj;
|
||||
use std::task::{
|
||||
Context, Poll,
|
||||
Wake, Waker, LocalWaker,
|
||||
Executor, TaskObj, SpawnObjError,
|
||||
Executor, SpawnObjError,
|
||||
local_waker, local_waker_from_nonlocal,
|
||||
};
|
||||
|
||||
@ -44,7 +45,7 @@ impl Wake for Counter {
|
||||
struct NoopExecutor;
|
||||
|
||||
impl Executor for NoopExecutor {
|
||||
fn spawn_obj(&mut self, _: TaskObj) -> Result<(), SpawnObjError> {
|
||||
fn spawn_obj(&mut self, _: FutureObj<'static, ()>) -> Result<(), SpawnObjError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user