From 50f8c68235faec2b9331f0ff36f4deb2f3d6cdab Mon Sep 17 00:00:00 2001 From: Tinco Andringa Date: Mon, 1 Apr 2019 00:16:46 +0200 Subject: [PATCH 1/3] Update to latest nightly, removing LocalWaker and introducing ArcWake --- src/arc_wake.rs | 78 +++++++++++++++++++++++++++++++++++++++++++ src/futures_future.rs | 6 ++-- src/lib.rs | 1 + src/std_future.rs | 6 ++-- 4 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 src/arc_wake.rs diff --git a/src/arc_wake.rs b/src/arc_wake.rs new file mode 100644 index 0000000..c74a621 --- /dev/null +++ b/src/arc_wake.rs @@ -0,0 +1,78 @@ +// From htttps://github.com/rust-lang/rustc +// +// Permission is hereby granted, free of charge, to any +// person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the +// Software without restriction, including without +// limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice +// shall be included in all copies or substantial portions +// of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +use std::sync::Arc; +use std::task::{ + Waker, RawWaker, RawWakerVTable, +}; + +macro_rules! waker_vtable { + ($ty:ident) => { + &RawWakerVTable { + clone: clone_arc_raw::<$ty>, + drop: drop_arc_raw::<$ty>, + wake: wake_arc_raw::<$ty>, + } + }; +} + +pub trait ArcWake { + fn wake(arc_self: &Arc); + + fn into_waker(wake: Arc) -> Waker where Self: Sized + { + let ptr = Arc::into_raw(wake) as *const(); + + unsafe { + Waker::new_unchecked(RawWaker::new(ptr, waker_vtable!(Self))) + } + } +} + +unsafe fn increase_refcount(data: *const()) { + // Retain Arc by creating a copy + let arc: Arc = Arc::from_raw(data as *const T); + let arc_clone = arc.clone(); + // Forget the Arcs again, so that the refcount isn't decrased + let _ = Arc::into_raw(arc); + let _ = Arc::into_raw(arc_clone); +} + +unsafe fn clone_arc_raw(data: *const()) -> RawWaker { + increase_refcount::(data); + RawWaker::new(data, waker_vtable!(T)) +} + +unsafe fn drop_arc_raw(data: *const()) { + // Drop Arc + let _: Arc = Arc::from_raw(data as *const T); +} + +unsafe fn wake_arc_raw(data: *const()) { + let arc: Arc = Arc::from_raw(data as *const T); + ArcWake::wake(&arc); + let _ = Arc::into_raw(arc); +} diff --git a/src/futures_future.rs b/src/futures_future.rs index 8e6c8ea..b88224a 100644 --- a/src/futures_future.rs +++ b/src/futures_future.rs @@ -1,9 +1,9 @@ //! 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 super::arc_wake::ArcWake; /// Adapter providing the [`futures::Future`] interface for other future types. pub struct FutureAdapter(pub Inner); @@ -18,7 +18,7 @@ struct TaskWaker { task: futures::task::Task, } -impl std::task::Wake for TaskWaker { +impl ArcWake for TaskWaker { fn wake(arc_self: &Arc) { arc_self.task.notify(); } @@ -33,7 +33,7 @@ impl futures::Future for FutureAdapter futures::Poll { - let wake = unsafe { std::task::local_waker(Arc::new(TaskWaker{task: futures::task::current()})) }; + let wake = ArcWake::into_waker(Arc::new(TaskWaker{task: futures::task::current()})); match self.0.as_mut().poll(&wake) { std::task::Poll::Pending => Ok(futures::Async::NotReady), diff --git a/src/lib.rs b/src/lib.rs index 90fbf4c..e8b4797 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,6 +41,7 @@ pub mod std_future; pub mod futures_future; +mod arc_wake; use std::pin::Pin; diff --git a/src/std_future.rs b/src/std_future.rs index 4336fc8..a7198c1 100644 --- a/src/std_future.rs +++ b/src/std_future.rs @@ -23,8 +23,8 @@ impl futures::executor::Notify for WakerNotifier { impl FutureAdapter> where F: futures::Future, { - fn poll(&mut self, waker: &std::task::LocalWaker) -> std::task::Poll> { - 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> { + let notify = futures::executor::NotifyHandle::from(Arc::new(WakerNotifier{waker: waker.clone()})); match self.0.poll_future_notify(¬ify, 0) { Ok(futures::Async::NotReady) => std::task::Poll::Pending, @@ -40,7 +40,7 @@ impl std::future::Future for FutureAdapter; - fn poll(self: Pin<&mut Self>, waker: &std::task::LocalWaker) -> std::task::Poll { + fn poll(self: Pin<&mut Self>, waker: &std::task::Waker) -> std::task::Poll { Pin::get_mut(self).poll(waker) } } From 0745c3c35c900c2001c6bbd89a1f38cb0560677e Mon Sep 17 00:00:00 2001 From: Tinco Andringa Date: Fri, 12 Apr 2019 12:57:53 +0200 Subject: [PATCH 2/3] Move arc_wake license to license file --- LICENSE | 26 ++++++++++++++++++++++++++ src/arc_wake.rs | 24 ------------------------ 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/LICENSE b/LICENSE index db1da40..d421171 100644 --- a/LICENSE +++ b/LICENSE @@ -20,3 +20,29 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# License below pertains specifically to the file src/arc_wake.rs + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/src/arc_wake.rs b/src/arc_wake.rs index c74a621..dab3f2d 100644 --- a/src/arc_wake.rs +++ b/src/arc_wake.rs @@ -1,28 +1,4 @@ // From htttps://github.com/rust-lang/rustc -// -// Permission is hereby granted, free of charge, to any -// person obtaining a copy of this software and associated -// documentation files (the "Software"), to deal in the -// Software without restriction, including without -// limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following -// conditions: -// -// The above copyright notice and this permission notice -// shall be included in all copies or substantial portions -// of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. use std::sync::Arc; use std::task::{ From 9fff2cc010419894381a20a8a4822416f840a8e9 Mon Sep 17 00:00:00 2001 From: Maarten de Vries Date: Fri, 12 Apr 2019 19:50:08 +0200 Subject: [PATCH 3/3] Implement RawWakerVTable directly for TaskWaker. --- LICENSE | 26 --------------------- src/arc_wake.rs | 54 ------------------------------------------- src/futures_future.rs | 40 ++++++++++++++++++++++++++------ src/lib.rs | 1 - src/std_future.rs | 4 ++-- 5 files changed, 35 insertions(+), 90 deletions(-) delete mode 100644 src/arc_wake.rs diff --git a/LICENSE b/LICENSE index d421171..db1da40 100644 --- a/LICENSE +++ b/LICENSE @@ -20,29 +20,3 @@ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# License below pertains specifically to the file src/arc_wake.rs - -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/src/arc_wake.rs b/src/arc_wake.rs deleted file mode 100644 index dab3f2d..0000000 --- a/src/arc_wake.rs +++ /dev/null @@ -1,54 +0,0 @@ -// From htttps://github.com/rust-lang/rustc - -use std::sync::Arc; -use std::task::{ - Waker, RawWaker, RawWakerVTable, -}; - -macro_rules! waker_vtable { - ($ty:ident) => { - &RawWakerVTable { - clone: clone_arc_raw::<$ty>, - drop: drop_arc_raw::<$ty>, - wake: wake_arc_raw::<$ty>, - } - }; -} - -pub trait ArcWake { - fn wake(arc_self: &Arc); - - fn into_waker(wake: Arc) -> Waker where Self: Sized - { - let ptr = Arc::into_raw(wake) as *const(); - - unsafe { - Waker::new_unchecked(RawWaker::new(ptr, waker_vtable!(Self))) - } - } -} - -unsafe fn increase_refcount(data: *const()) { - // Retain Arc by creating a copy - let arc: Arc = Arc::from_raw(data as *const T); - let arc_clone = arc.clone(); - // Forget the Arcs again, so that the refcount isn't decrased - let _ = Arc::into_raw(arc); - let _ = Arc::into_raw(arc_clone); -} - -unsafe fn clone_arc_raw(data: *const()) -> RawWaker { - increase_refcount::(data); - RawWaker::new(data, waker_vtable!(T)) -} - -unsafe fn drop_arc_raw(data: *const()) { - // Drop Arc - let _: Arc = Arc::from_raw(data as *const T); -} - -unsafe fn wake_arc_raw(data: *const()) { - let arc: Arc = Arc::from_raw(data as *const T); - ArcWake::wake(&arc); - let _ = Arc::into_raw(arc); -} diff --git a/src/futures_future.rs b/src/futures_future.rs index b88224a..daa71d6 100644 --- a/src/futures_future.rs +++ b/src/futures_future.rs @@ -1,9 +1,9 @@ //! 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 super::arc_wake::ArcWake; + +use std::task::{RawWaker, RawWakerVTable}; /// Adapter providing the [`futures::Future`] interface for other future types. pub struct FutureAdapter(pub Inner); @@ -18,9 +18,34 @@ struct TaskWaker { task: futures::task::Task, } -impl ArcWake for TaskWaker { - fn wake(arc_self: &Arc) { - 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)) } } } @@ -33,9 +58,10 @@ impl futures::Future for FutureAdapter futures::Poll { - let wake = ArcWake::into_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), diff --git a/src/lib.rs b/src/lib.rs index e8b4797..90fbf4c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,7 +41,6 @@ pub mod std_future; pub mod futures_future; -mod arc_wake; use std::pin::Pin; diff --git a/src/std_future.rs b/src/std_future.rs index a7198c1..dc4d419 100644 --- a/src/std_future.rs +++ b/src/std_future.rs @@ -40,7 +40,7 @@ impl std::future::Future for FutureAdapter; - fn poll(self: Pin<&mut Self>, waker: &std::task::Waker) -> std::task::Poll { - Pin::get_mut(self).poll(waker) + fn poll(self: Pin<&mut Self>, context: &mut std::task::Context) -> std::task::Poll { + Pin::get_mut(self).poll(context.waker()) } }