Skip to content

Commit

Permalink
Merge pull request #1 from tinco/no_local_waker
Browse files Browse the repository at this point in the history
Update to latest nightly, removing LocalWaker and introducing ArcWake
  • Loading branch information
de-vri-es authored Apr 17, 2019
2 parents bd0447b + 9fff2cc commit 6218579
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 11 deletions.
40 changes: 33 additions & 7 deletions src/futures_future.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//! Provides the [`futures::Future`] interface for compatible types.
//!
//! Currently, only types implementing `std::future::Future` are supported.
use std::sync::Arc;
use std::pin::Pin;

use std::task::{RawWaker, RawWakerVTable};

/// Adapter providing the [`futures::Future`] interface for other future types.
pub struct FutureAdapter<Inner>(pub Inner);

Expand All @@ -18,9 +18,34 @@ struct TaskWaker {
task: futures::task::Task,
}

impl std::task::Wake for TaskWaker {
fn wake(arc_self: &Arc<Self>) {
arc_self.task.notify();
const TASK_WAKER_VTABLE : RawWakerVTable = RawWakerVTable::new(
clone_task_waker,
drop_task_waker,
wake_task_waker,
);

unsafe fn clone_task_waker(data: *const ()) -> RawWaker {
let data = &*(data as *const TaskWaker);
TaskWaker::into_raw_waker(data.task.clone())
}

unsafe fn drop_task_waker(data: *const ()) {
Box::from_raw(data as *mut TaskWaker);
}

unsafe fn wake_task_waker(data: *const ()) {
let data = &*(data as *const TaskWaker);
data.task.notify();
}

impl TaskWaker {
unsafe fn into_raw_waker(task: futures::task::Task) -> RawWaker {
let data = Box::leak(Box::new(task)) as *const _ as *const ();
RawWaker::new(data, &TASK_WAKER_VTABLE)
}

fn into_waker(task: futures::task::Task) -> std::task::Waker {
unsafe { std::task::Waker::new_unchecked(TaskWaker::into_raw_waker(task)) }
}
}

Expand All @@ -33,9 +58,10 @@ impl<Pointer, Future, Item, Error> futures::Future for FutureAdapter<Pin<Pointer
type Error = Error;

fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
let wake = unsafe { std::task::local_waker(Arc::new(TaskWaker{task: futures::task::current()})) };
let waker = TaskWaker::into_waker(futures::task::current());
let mut context = std::task::Context::from_waker(&waker);

match self.0.as_mut().poll(&wake) {
match self.0.as_mut().poll(&mut context) {
std::task::Poll::Pending => Ok(futures::Async::NotReady),
std::task::Poll::Ready(Ok(val)) => Ok(futures::Async::Ready(val)),
std::task::Poll::Ready(Err(err)) => Err(err),
Expand Down
8 changes: 4 additions & 4 deletions src/std_future.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ impl futures::executor::Notify for WakerNotifier {
impl<F, Item, Error> FutureAdapter<futures::executor::Spawn<F>> where
F: futures::Future<Item=Item, Error=Error>,
{
fn poll(&mut self, waker: &std::task::LocalWaker) -> std::task::Poll<Result<Item, Error>> {
let notify = futures::executor::NotifyHandle::from(Arc::new(WakerNotifier{waker: waker.clone().into_waker()}));
fn poll(&mut self, waker: &std::task::Waker) -> std::task::Poll<Result<Item, Error>> {
let notify = futures::executor::NotifyHandle::from(Arc::new(WakerNotifier{waker: waker.clone()}));

match self.0.poll_future_notify(&notify, 0) {
Ok(futures::Async::NotReady) => std::task::Poll::Pending,
Expand All @@ -40,7 +40,7 @@ impl<F, Item, Error> std::future::Future for FutureAdapter<futures::executor::Sp
{
type Output = Result<Item, Error>;

fn poll(self: Pin<&mut Self>, waker: &std::task::LocalWaker) -> std::task::Poll<Self::Output> {
Pin::get_mut(self).poll(waker)
fn poll(self: Pin<&mut Self>, context: &mut std::task::Context) -> std::task::Poll<Self::Output> {
Pin::get_mut(self).poll(context.waker())
}
}

0 comments on commit 6218579

Please sign in to comment.