Skip to content

Commit

Permalink
Remove spawning from task::Context
Browse files Browse the repository at this point in the history
  • Loading branch information
cramertj committed Sep 19, 2018
1 parent 20dc0c5 commit 1b00f0b
Show file tree
Hide file tree
Showing 13 changed files with 93 additions and 568 deletions.
71 changes: 4 additions & 67 deletions src/liballoc/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ use core::borrow;
use core::cmp::Ordering;
use core::convert::From;
use core::fmt;
use core::future::{Future, FutureObj, LocalFutureObj, UnsafeFutureObj};
use core::future::Future;
use core::hash::{Hash, Hasher};
use core::iter::FusedIterator;
use core::marker::{Unpin, Unsize};
use core::mem;
use core::pin::Pin;
use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
use core::ptr::{self, NonNull, Unique};
use core::task::{Context, Poll, Spawn, SpawnErrorKind, SpawnObjError};
use core::task::{LocalWaker, Poll};

use raw_vec::RawVec;
use str::from_boxed_utf8_unchecked;
Expand Down Expand Up @@ -804,70 +804,7 @@ impl<T> Generator for Box<T>
impl<F: ?Sized + Future + Unpin> Future for Box<F> {
type Output = F::Output;

fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
F::poll(Pin::new(&mut *self), cx)
}
}

#[unstable(feature = "futures_api", issue = "50547")]
unsafe impl<'a, T, F> UnsafeFutureObj<'a, T> for Box<F>
where F: Future<Output = T> + 'a
{
fn into_raw(self) -> *mut () {
Box::into_raw(self) as *mut ()
}

unsafe fn poll(ptr: *mut (), cx: &mut Context) -> Poll<T> {
let ptr = ptr as *mut F;
let pin: Pin<&mut F> = Pin::new_unchecked(&mut *ptr);
F::poll(pin, cx)
}

unsafe fn drop(ptr: *mut ()) {
drop(Box::from_raw(ptr as *mut F))
}
}

#[unstable(feature = "futures_api", issue = "50547")]
impl<Sp> Spawn for Box<Sp>
where Sp: Spawn + ?Sized
{
fn spawn_obj(
&mut self,
future: FutureObj<'static, ()>,
) -> Result<(), SpawnObjError> {
(**self).spawn_obj(future)
}

fn status(&self) -> Result<(), SpawnErrorKind> {
(**self).status()
}
}

#[unstable(feature = "futures_api", issue = "50547")]
impl<'a, F: Future<Output = ()> + Send + 'a> From<Box<F>> for FutureObj<'a, ()> {
fn from(boxed: Box<F>) -> Self {
FutureObj::new(boxed)
}
}

#[unstable(feature = "futures_api", issue = "50547")]
impl<'a, F: Future<Output = ()> + 'a> From<Box<F>> for LocalFutureObj<'a, ()> {
fn from(boxed: Box<F>) -> Self {
LocalFutureObj::new(boxed)
}
}

#[unstable(feature = "futures_api", issue = "50547")]
impl<'a, F: Future<Output = ()> + Send + 'a> From<Pin<Box<F>>> for FutureObj<'a, ()> {
fn from(boxed: Pin<Box<F>>) -> Self {
FutureObj::new(boxed)
}
}

#[unstable(feature = "futures_api", issue = "50547")]
impl<'a, F: Future<Output = ()> + 'a> From<Pin<Box<F>>> for LocalFutureObj<'a, ()> {
fn from(boxed: Pin<Box<F>>) -> Self {
LocalFutureObj::new(boxed)
fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
F::poll(Pin::new(&mut *self), lw)
}
}
55 changes: 34 additions & 21 deletions src/libcore/future/future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use marker::Unpin;
use ops;
use pin::Pin;
use task::{self, Poll};
use task::{Poll, LocalWaker};

/// A future represents an asychronous computation.
///
Expand Down Expand Up @@ -50,28 +50,28 @@ pub trait Future {
///
/// Once a future has finished, clients should not `poll` it again.
///
/// When a future is not ready yet, `poll` returns
/// `Poll::Pending`. The future will *also* register the
/// interest of the current task in the value being produced. For example,
/// if the future represents the availability of data on a socket, then the
/// task is recorded so that when data arrives, it is woken up (via
/// [`cx.waker()`]). Once a task has been woken up,
/// it should attempt to `poll` the future again, which may or may not
/// produce a final value.
/// When a future is not ready yet, `poll` returns `Poll::Pending` and
/// stores a clone of the [`LocalWaker`] to be woken once the future can
/// make progress. For example, a future waiting for a socket to become
/// readable would call `.clone()` on the [`LocalWaker`] and store it.
/// When a signal arrives elsewhere indicating that the socket is readable,
/// `[LocalWaker::wake]` is called and the socket future's task is awoken.
/// Once a task has been woken up, it should attempt to `poll` the future
/// again, which may or may not produce a final value.
///
/// Note that if `Pending` is returned it only means that the *current* task
/// (represented by the argument `cx`) will receive a notification. Tasks
/// from previous calls to `poll` will *not* receive notifications.
/// Note that on multiple calls to `poll`, only the most recent
/// [`LocalWaker`] passed to `poll` should be scheduled to receive a
/// wakeup.
///
/// # Runtime characteristics
///
/// Futures alone are *inert*; they must be *actively* `poll`ed to make
/// progress, meaning that each time the current task is woken up, it should
/// actively re-`poll` pending futures that it still has an interest in.
///
/// The `poll` function is not called repeatedly in a tight loop for
/// futures, but only whenever the future itself is ready, as signaled via
/// the `Waker` inside `task::Context`. If you're familiar with the
/// The `poll` function is not called repeatedly in a tight loop-- instead,
/// it should only be called when the future indicates that it is ready to
/// make progress (by calling `wake()`). If you're familiar with the
/// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
/// typically do *not* suffer the same problems of "all wakeups must poll
/// all events"; they are more like `epoll(4)`.
Expand All @@ -83,6 +83,16 @@ pub trait Future {
/// thread pool (or something similar) to ensure that `poll` can return
/// quickly.
///
/// # [`LocalWaker`], [`Waker`] and thread-safety
///
/// The `poll` function takes a [`LocalWaker`], an object which knows how to
/// awaken the current task. [`LocalWaker`] is not `Send` nor `Sync`, so in
/// order to make thread-safe futures the [`LocalWaker::into_waker`] method
/// should be used to convert the [`LocalWaker`] into a thread-safe version.
/// [`LocalWaker::wake`] implementations have the ability to be more
/// efficient, however, so when thread safety is not necessary,
/// [`LocalWaker`] should be preferred.
///
/// # Panics
///
/// Once a future has completed (returned `Ready` from `poll`),
Expand All @@ -92,15 +102,18 @@ pub trait Future {
///
/// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
/// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
/// [`cx.waker()`]: ../task/struct.Context.html#method.waker
fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output>;
/// [`LocalWaker`]: ../task/struct.LocalWaker.html
/// [`LocalWaker::into_waker`]: ../task/struct.LocalWaker.html#method.into_waker
/// [`LocalWaker::wake`]: ../task/struct.LocalWaker.html#method.wake
/// [`Waker`]: ../task/struct.Waker.html
fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output>;
}

impl<'a, F: ?Sized + Future + Unpin> Future for &'a mut F {
type Output = F::Output;

fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {
F::poll(Pin::new(&mut **self), cx)
fn poll(mut self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
F::poll(Pin::new(&mut **self), lw)
}
}

Expand All @@ -111,7 +124,7 @@ where
{
type Output = <<P as ops::Deref>::Target as Future>::Output;

fn poll(self: Pin<&mut Self>, cx: &mut task::Context) -> Poll<Self::Output> {
Pin::get_mut(self).as_mut().poll(cx)
fn poll(self: Pin<&mut Self>, lw: &LocalWaker) -> Poll<Self::Output> {
Pin::get_mut(self).as_mut().poll(lw)
}
}
203 changes: 0 additions & 203 deletions src/libcore/future/future_obj.rs

This file was deleted.

Loading

0 comments on commit 1b00f0b

Please sign in to comment.