1#![doc(html_root_url = "https://docs.rs/task-compat/0.1.0")]
4#![warn(
5 missing_debug_implementations,
6 missing_docs,
7 rust_2018_idioms,
8 unreachable_pub
9)]
10
11use futures01::{
12 executor::{Notify, NotifyHandle, UnsafeNotify},
13 Async, Poll as Poll01,
14};
15use futures03::task::{ArcWake, WakerRef};
16use std::{
17 sync::Arc,
18 task::{Context, Poll as Poll03, RawWaker, RawWakerVTable, Waker},
19};
20
21pub fn with_notify<F, R>(cx: &mut Context<'_>, f: F) -> R
24where
25 F: FnOnce() -> R,
26{
27 let mut spawn = futures01::task::spawn(());
28
29 let notify = Arc::new(NotifyWaker(cx.waker().clone()));
32
33 spawn.poll_fn_notify(¬ify, 0, |_| f())
34}
35
36pub fn with_context<F, R>(f: F) -> R
38where
39 F: FnOnce(&mut Context<'_>) -> R,
40{
41 let current = Current::new();
42 let waker = current.as_waker();
43 let mut cx = Context::from_waker(&waker);
44
45 f(&mut cx)
46}
47
48pub fn poll_03_to_01<T, E>(x: Poll03<Result<T, E>>) -> Poll01<T, E> {
50 match x? {
51 Poll03::Ready(t) => Ok(Async::Ready(t)),
52 Poll03::Pending => Ok(Async::NotReady),
53 }
54}
55
56pub fn poll_01_to_03<T, E>(x: Poll01<T, E>) -> Poll03<Result<T, E>> {
58 match x {
59 Ok(Async::Ready(v)) => Poll03::Ready(Ok(v)),
60 Ok(Async::NotReady) => Poll03::Pending,
61 Err(e) => Poll03::Ready(Err(e)),
62 }
63}
64
65struct NotifyWaker(Waker);
68
69#[derive(Clone)]
70struct WakerToHandle<'a>(&'a Waker);
71
72impl From<WakerToHandle<'_>> for NotifyHandle {
73 fn from(handle: WakerToHandle<'_>) -> NotifyHandle {
74 let ptr = Box::new(NotifyWaker(handle.0.clone()));
75
76 unsafe { NotifyHandle::new(Box::into_raw(ptr)) }
77 }
78}
79
80impl Notify for NotifyWaker {
81 fn notify(&self, _: usize) {
82 self.0.wake_by_ref();
83 }
84}
85
86unsafe impl UnsafeNotify for NotifyWaker {
87 unsafe fn clone_raw(&self) -> NotifyHandle {
88 WakerToHandle(&self.0).into()
89 }
90
91 unsafe fn drop_raw(&self) {
92 let ptr: *const dyn UnsafeNotify = self;
93 drop(Box::from_raw(ptr as *mut dyn UnsafeNotify));
94 }
95}
96
97#[derive(Clone)]
98struct Current(futures01::task::Task);
99
100impl Current {
101 fn new() -> Current {
102 Current(futures01::task::current())
103 }
104
105 fn as_waker(&self) -> WakerRef<'_> {
106 unsafe fn ptr_to_current<'a>(ptr: *const ()) -> &'a Current {
107 &*(ptr as *const Current)
108 }
109 fn current_to_ptr(current: &Current) -> *const () {
110 current as *const Current as *const ()
111 }
112
113 unsafe fn clone(ptr: *const ()) -> RawWaker {
114 std::mem::transmute::<Waker, RawWaker>(futures03::task::waker(Arc::new(
118 ptr_to_current(ptr).clone(),
119 )))
120 }
121 unsafe fn drop(_: *const ()) {}
122 unsafe fn wake(ptr: *const ()) {
123 ptr_to_current(ptr).0.notify()
124 }
125
126 let ptr = current_to_ptr(self);
127 let vtable = &RawWakerVTable::new(clone, wake, wake, drop);
128 futures03::task::WakerRef::new_unowned(std::mem::ManuallyDrop::new(unsafe {
129 futures03::task::Waker::from_raw(RawWaker::new(ptr, vtable))
130 }))
131 }
132}
133
134impl ArcWake for Current {
135 fn wake_by_ref(arc_self: &Arc<Self>) {
136 arc_self.0.notify();
137 }
138}