feat(lib): update to std::future::Future
				
					
				
			BREAKING CHANGE: All usage of async traits (`Future`, `Stream`, `AsyncRead`, `AsyncWrite`, etc) are updated to newer versions.
This commit is contained in:
		| @@ -1,14 +1,19 @@ | ||||
| use std::mem; | ||||
|  | ||||
| use futures::{Async, Future, Poll, Stream}; | ||||
| use futures::future::Shared; | ||||
| use futures::sync::{mpsc, oneshot}; | ||||
| use tokio_sync::{mpsc, watch}; | ||||
|  | ||||
| use super::Never; | ||||
| use super::{Future, Never, Poll, Pin, task}; | ||||
|  | ||||
| // Sentinel value signaling that the watch is still open | ||||
| enum Action { | ||||
|     Open, | ||||
|     // Closed isn't sent via the `Action` type, but rather once | ||||
|     // the watch::Sender is dropped. | ||||
| } | ||||
|  | ||||
| pub fn channel() -> (Signal, Watch) { | ||||
|     let (tx, rx) = oneshot::channel(); | ||||
|     let (drained_tx, drained_rx) = mpsc::channel(0); | ||||
|     let (tx, rx) = watch::channel(Action::Open); | ||||
|     let (drained_tx, drained_rx) = mpsc::channel(1); | ||||
|     ( | ||||
|         Signal { | ||||
|             drained_rx, | ||||
| @@ -16,14 +21,14 @@ pub fn channel() -> (Signal, Watch) { | ||||
|         }, | ||||
|         Watch { | ||||
|             drained_tx, | ||||
|             rx: rx.shared(), | ||||
|             rx, | ||||
|         }, | ||||
|     ) | ||||
| } | ||||
|  | ||||
| pub struct Signal { | ||||
|     drained_rx: mpsc::Receiver<Never>, | ||||
|     tx: oneshot::Sender<()>, | ||||
|     tx: watch::Sender<Action>, | ||||
| } | ||||
|  | ||||
| pub struct Draining { | ||||
| @@ -33,7 +38,7 @@ pub struct Draining { | ||||
| #[derive(Clone)] | ||||
| pub struct Watch { | ||||
|     drained_tx: mpsc::Sender<Never>, | ||||
|     rx: Shared<oneshot::Receiver<()>>, | ||||
|     rx: watch::Receiver<Action>, | ||||
| } | ||||
|  | ||||
| #[allow(missing_debug_implementations)] | ||||
| @@ -50,7 +55,7 @@ enum State<F> { | ||||
|  | ||||
| impl Signal { | ||||
|     pub fn drain(self) -> Draining { | ||||
|         let _ = self.tx.send(()); | ||||
|         // Simply dropping `self.tx` will signal the watchers | ||||
|         Draining { | ||||
|             drained_rx: self.drained_rx, | ||||
|         } | ||||
| @@ -58,13 +63,12 @@ impl Signal { | ||||
| } | ||||
|  | ||||
| impl Future for Draining { | ||||
|     type Item = (); | ||||
|     type Error = (); | ||||
|     type Output = (); | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|         match try_ready!(self.drained_rx.poll()) { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         match ready!(self.drained_rx.poll_recv(cx)) { | ||||
|             Some(never) => match never {}, | ||||
|             None => Ok(Async::Ready(())), | ||||
|             None => Poll::Ready(()), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -73,7 +77,7 @@ impl Watch { | ||||
|     pub fn watch<F, FN>(self, future: F, on_drain: FN) -> Watching<F, FN> | ||||
|     where | ||||
|         F: Future, | ||||
|         FN: FnOnce(&mut F), | ||||
|         FN: FnOnce(Pin<&mut F>), | ||||
|     { | ||||
|         Watching { | ||||
|             future, | ||||
| @@ -86,28 +90,29 @@ impl Watch { | ||||
| impl<F, FN> Future for Watching<F, FN> | ||||
| where | ||||
|     F: Future, | ||||
|     FN: FnOnce(&mut F), | ||||
|     FN: FnOnce(Pin<&mut F>), | ||||
| { | ||||
|     type Item = F::Item; | ||||
|     type Error = F::Error; | ||||
|     type Output = F::Output; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         let me = unsafe { self.get_unchecked_mut() }; | ||||
|         loop { | ||||
|             match mem::replace(&mut self.state, State::Draining) { | ||||
|             match mem::replace(&mut me.state, State::Draining) { | ||||
|                 State::Watch(on_drain) => { | ||||
|                     match self.watch.rx.poll() { | ||||
|                         Ok(Async::Ready(_)) | Err(_) => { | ||||
|                     match me.watch.rx.poll_ref(cx) { | ||||
|                         Poll::Ready(None) => { | ||||
|                             // Drain has been triggered! | ||||
|                             on_drain(&mut self.future); | ||||
|                             on_drain(unsafe { Pin::new_unchecked(&mut me.future) }); | ||||
|                         }, | ||||
|                         Ok(Async::NotReady) => { | ||||
|                             self.state = State::Watch(on_drain); | ||||
|                             return self.future.poll(); | ||||
|                         Poll::Ready(Some(_/*State::Open*/)) | | ||||
|                         Poll::Pending => { | ||||
|                             me.state = State::Watch(on_drain); | ||||
|                             return unsafe { Pin::new_unchecked(&mut me.future) }.poll(cx); | ||||
|                         }, | ||||
|                     } | ||||
|                 }, | ||||
|                 State::Draining => { | ||||
|                     return self.future.poll(); | ||||
|                     return unsafe { Pin::new_unchecked(&mut me.future) }.poll(cx); | ||||
|                 }, | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| use std::fmt; | ||||
| use std::future::Future; | ||||
| use std::pin::Pin; | ||||
| use std::sync::Arc; | ||||
|  | ||||
| use futures::future::{Executor, Future}; | ||||
| use tokio_executor::TypedExecutor; | ||||
|  | ||||
| use crate::body::Payload; | ||||
| use crate::proto::h2::server::H2Stream; | ||||
| @@ -9,11 +11,11 @@ use crate::server::conn::spawn_all::{NewSvcTask, Watcher}; | ||||
| use crate::service::Service; | ||||
|  | ||||
| pub trait H2Exec<F, B: Payload>: Clone { | ||||
|     fn execute_h2stream(&self, fut: H2Stream<F, B>) -> crate::Result<()>; | ||||
|     fn execute_h2stream(&mut self, fut: H2Stream<F, B>) -> crate::Result<()>; | ||||
| } | ||||
|  | ||||
| pub trait NewSvcExec<I, N, S: Service, E, W: Watcher<I, S, E>>: Clone { | ||||
|     fn execute_new_svc(&self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()>; | ||||
|     fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()>; | ||||
| } | ||||
|  | ||||
| // Either the user provides an executor for background tasks, or we use | ||||
| @@ -21,7 +23,7 @@ pub trait NewSvcExec<I, N, S: Service, E, W: Watcher<I, S, E>>: Clone { | ||||
| #[derive(Clone)] | ||||
| pub enum Exec { | ||||
|     Default, | ||||
|     Executor(Arc<dyn Executor<Box<dyn Future<Item=(), Error=()> + Send>> + Send + Sync>), | ||||
|     Executor(Arc<dyn TypedExecutor<Pin<Box<dyn Future<Output=()> + Send>>> + Send + Sync>), | ||||
| } | ||||
|  | ||||
| // ===== impl Exec ===== | ||||
| @@ -29,14 +31,13 @@ pub enum Exec { | ||||
| impl Exec { | ||||
|     pub(crate) fn execute<F>(&self, fut: F) -> crate::Result<()> | ||||
|     where | ||||
|         F: Future<Item=(), Error=()> + Send + 'static, | ||||
|         F: Future<Output=()> + Send + 'static, | ||||
|     { | ||||
|         match *self { | ||||
|             Exec::Default => { | ||||
|                 #[cfg(feature = "runtime")] | ||||
|                 { | ||||
|                     use std::error::Error as StdError; | ||||
|                     use ::tokio_executor::Executor; | ||||
|  | ||||
|                     struct TokioSpawnError; | ||||
|  | ||||
| @@ -59,7 +60,7 @@ impl Exec { | ||||
|                     } | ||||
|  | ||||
|                     ::tokio_executor::DefaultExecutor::current() | ||||
|                         .spawn(Box::new(fut)) | ||||
|                         .spawn(Box::pin(fut)) | ||||
|                         .map_err(|err| { | ||||
|                             warn!("executor error: {:?}", err); | ||||
|                             crate::Error::new_execute(TokioSpawnError) | ||||
| @@ -72,11 +73,14 @@ impl Exec { | ||||
|                 } | ||||
|             }, | ||||
|             Exec::Executor(ref e) => { | ||||
|                 e.execute(Box::new(fut)) | ||||
|                 unimplemented!("custom executor exec"); | ||||
|                 /* XXX: needs mut | ||||
|                 e.spawn(Box::pin(fut)) | ||||
|                     .map_err(|err| { | ||||
|                         warn!("executor error: {:?}", err.kind()); | ||||
|                         warn!("executor error: {:?}", err); | ||||
|                         crate::Error::new_execute("custom executor failed") | ||||
|                     }) | ||||
|                     */ | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| @@ -92,21 +96,21 @@ impl fmt::Debug for Exec { | ||||
|  | ||||
| impl<F, B> H2Exec<F, B> for Exec | ||||
| where | ||||
|     H2Stream<F, B>: Future<Item=(), Error=()> + Send + 'static, | ||||
|     H2Stream<F, B>: Future<Output = ()> + Send + 'static, | ||||
|     B: Payload, | ||||
| { | ||||
|     fn execute_h2stream(&self, fut: H2Stream<F, B>) -> crate::Result<()> { | ||||
|     fn execute_h2stream(&mut self, fut: H2Stream<F, B>) -> crate::Result<()> { | ||||
|         self.execute(fut) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for Exec | ||||
| where | ||||
|     NewSvcTask<I, N, S, E, W>: Future<Item=(), Error=()> + Send + 'static, | ||||
|     NewSvcTask<I, N, S, E, W>: Future<Output=()> + Send + 'static, | ||||
|     S: Service, | ||||
|     W: Watcher<I, S, E>, | ||||
| { | ||||
|     fn execute_new_svc(&self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> { | ||||
|     fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> { | ||||
|         self.execute(fut) | ||||
|     } | ||||
| } | ||||
| @@ -115,14 +119,14 @@ where | ||||
|  | ||||
| impl<E, F, B> H2Exec<F, B> for E | ||||
| where | ||||
|     E: Executor<H2Stream<F, B>> + Clone, | ||||
|     H2Stream<F, B>: Future<Item=(), Error=()>, | ||||
|     E: TypedExecutor<H2Stream<F, B>> + Clone, | ||||
|     H2Stream<F, B>: Future<Output=()>, | ||||
|     B: Payload, | ||||
| { | ||||
|     fn execute_h2stream(&self, fut: H2Stream<F, B>) -> crate::Result<()> { | ||||
|         self.execute(fut) | ||||
|     fn execute_h2stream(&mut self, fut: H2Stream<F, B>) -> crate::Result<()> { | ||||
|         self.spawn(fut) | ||||
|             .map_err(|err| { | ||||
|                 warn!("executor error: {:?}", err.kind()); | ||||
|                 warn!("executor error: {:?}", err); | ||||
|                 crate::Error::new_execute("custom executor failed") | ||||
|             }) | ||||
|     } | ||||
| @@ -130,15 +134,15 @@ where | ||||
|  | ||||
| impl<I, N, S, E, W> NewSvcExec<I, N, S, E, W> for E | ||||
| where | ||||
|     E: Executor<NewSvcTask<I, N, S, E, W>> + Clone, | ||||
|     NewSvcTask<I, N, S, E, W>: Future<Item=(), Error=()>, | ||||
|     E: TypedExecutor<NewSvcTask<I, N, S, E, W>> + Clone, | ||||
|     NewSvcTask<I, N, S, E, W>: Future<Output=()>, | ||||
|     S: Service, | ||||
|     W: Watcher<I, S, E>, | ||||
| { | ||||
|     fn execute_new_svc(&self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> { | ||||
|         self.execute(fut) | ||||
|     fn execute_new_svc(&mut self, fut: NewSvcTask<I, N, S, E, W>) -> crate::Result<()> { | ||||
|         self.spawn(fut) | ||||
|             .map_err(|err| { | ||||
|                 warn!("executor error: {:?}", err.kind()); | ||||
|                 warn!("executor error: {:?}", err); | ||||
|                 crate::Error::new_execute("custom executor failed") | ||||
|             }) | ||||
|     } | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| use std::cmp; | ||||
| use std::io::{self, Read, Write}; | ||||
| use std::io::{self, Read}; | ||||
| use std::marker::Unpin; | ||||
|  | ||||
| use bytes::{Buf, BufMut, Bytes, IntoBuf}; | ||||
| use futures::{Async, Poll}; | ||||
| use tokio_io::{AsyncRead, AsyncWrite}; | ||||
|  | ||||
| use crate::common::{Pin, Poll, task}; | ||||
|  | ||||
| /// Combine a buffer with an IO, rewinding reads to use the buffer. | ||||
| #[derive(Debug)] | ||||
| pub(crate) struct Rewind<T> { | ||||
| @@ -37,12 +38,16 @@ impl<T> Rewind<T> { | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T> Read for Rewind<T> | ||||
| impl<T> AsyncRead for Rewind<T> | ||||
| where | ||||
|     T: Read, | ||||
|     T: AsyncRead + Unpin, | ||||
| { | ||||
|     #[inline] | ||||
|     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { | ||||
|     unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { | ||||
|         self.inner.prepare_uninitialized_buffer(buf) | ||||
|     } | ||||
|  | ||||
|     fn poll_read(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>> { | ||||
|         if let Some(pre_bs) = self.pre.take() { | ||||
|             // If there are no remaining bytes, let the bytes get dropped. | ||||
|             if pre_bs.len() > 0 { | ||||
| @@ -57,39 +62,17 @@ where | ||||
|                     self.pre = Some(new_pre); | ||||
|                 } | ||||
|  | ||||
|                 return Ok(read_cnt); | ||||
|                 return Poll::Ready(Ok(read_cnt)); | ||||
|             } | ||||
|         } | ||||
|         self.inner.read(buf) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T> Write for Rewind<T> | ||||
| where | ||||
|     T: Write, | ||||
| { | ||||
|     #[inline] | ||||
|     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | ||||
|         self.inner.write(buf) | ||||
|     } | ||||
|  | ||||
|     #[inline] | ||||
|     fn flush(&mut self) -> io::Result<()> { | ||||
|         self.inner.flush() | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<T> AsyncRead for Rewind<T> | ||||
| where | ||||
|     T: AsyncRead, | ||||
| { | ||||
|     #[inline] | ||||
|     unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [u8]) -> bool { | ||||
|         self.inner.prepare_uninitialized_buffer(buf) | ||||
|         Pin::new(&mut self.inner).poll_read(cx, buf) | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     #[inline] | ||||
|     fn read_buf<B: BufMut>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { | ||||
|         use std::cmp; | ||||
|  | ||||
|         if let Some(bs) = self.pre.take() { | ||||
|             let pre_len = bs.len(); | ||||
|             // If there are no remaining bytes, let the bytes get dropped. | ||||
| @@ -112,21 +95,31 @@ where | ||||
|         } | ||||
|         self.inner.read_buf(buf) | ||||
|     } | ||||
|     */ | ||||
| } | ||||
|  | ||||
| impl<T> AsyncWrite for Rewind<T> | ||||
| where | ||||
|     T: AsyncWrite, | ||||
|     T: AsyncWrite + Unpin, | ||||
| { | ||||
|     #[inline] | ||||
|     fn shutdown(&mut self) -> Poll<(), io::Error> { | ||||
|         AsyncWrite::shutdown(&mut self.inner) | ||||
|     fn poll_write(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> { | ||||
|         Pin::new(&mut self.inner).poll_write(cx, buf) | ||||
|     } | ||||
|  | ||||
|     fn poll_flush(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|         Pin::new(&mut self.inner).poll_flush(cx) | ||||
|     } | ||||
|  | ||||
|     fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> { | ||||
|         Pin::new(&mut self.inner).poll_shutdown(cx) | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|     #[inline] | ||||
|     fn write_buf<B: Buf>(&mut self, buf: &mut B) -> Poll<usize, io::Error> { | ||||
|         self.inner.write_buf(buf) | ||||
|     } | ||||
|     */ | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| use std::mem; | ||||
|  | ||||
| use futures::{Future, IntoFuture, Poll}; | ||||
| use super::{Future, Pin, Poll, task}; | ||||
|  | ||||
| pub(crate) trait Started: Future { | ||||
|     fn started(&self) -> bool; | ||||
| @@ -9,7 +9,7 @@ pub(crate) trait Started: Future { | ||||
| pub(crate) fn lazy<F, R>(func: F) -> Lazy<F, R> | ||||
| where | ||||
|     F: FnOnce() -> R, | ||||
|     R: IntoFuture, | ||||
|     R: Future + Unpin, | ||||
| { | ||||
|     Lazy { | ||||
|         inner: Inner::Init(func), | ||||
| @@ -18,8 +18,8 @@ where | ||||
|  | ||||
| // FIXME: allow() required due to `impl Trait` leaking types to this lint | ||||
| #[allow(missing_debug_implementations)] | ||||
| pub(crate) struct Lazy<F, R: IntoFuture> { | ||||
|     inner: Inner<F, R::Future> | ||||
| pub(crate) struct Lazy<F, R> { | ||||
|     inner: Inner<F, R> | ||||
| } | ||||
|  | ||||
| enum Inner<F, R> { | ||||
| @@ -31,7 +31,7 @@ enum Inner<F, R> { | ||||
| impl<F, R> Started for Lazy<F, R> | ||||
| where | ||||
|     F: FnOnce() -> R, | ||||
|     R: IntoFuture, | ||||
|     R: Future + Unpin, | ||||
| { | ||||
|     fn started(&self) -> bool { | ||||
|         match self.inner { | ||||
| @@ -45,21 +45,20 @@ where | ||||
| impl<F, R> Future for Lazy<F, R> | ||||
| where | ||||
|     F: FnOnce() -> R, | ||||
|     R: IntoFuture, | ||||
|     R: Future + Unpin, | ||||
| { | ||||
|     type Item = R::Item; | ||||
|     type Error = R::Error; | ||||
|     type Output = R::Output; | ||||
|  | ||||
|     fn poll(&mut self) -> Poll<Self::Item, Self::Error> { | ||||
|     fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | ||||
|         match self.inner { | ||||
|             Inner::Fut(ref mut f) => return f.poll(), | ||||
|             Inner::Fut(ref mut f) => return Pin::new(f).poll(cx), | ||||
|             _ => (), | ||||
|         } | ||||
|  | ||||
|         match mem::replace(&mut self.inner, Inner::Empty) { | ||||
|             Inner::Init(func) => { | ||||
|                 let mut fut = func().into_future(); | ||||
|                 let ret = fut.poll(); | ||||
|                 let mut fut = func(); | ||||
|                 let ret = Pin::new(&mut fut).poll(cx); | ||||
|                 self.inner = Inner::Fut(fut); | ||||
|                 ret | ||||
|             }, | ||||
| @@ -68,3 +67,6 @@ where | ||||
|     } | ||||
| } | ||||
|  | ||||
| // The closure `F` is never pinned | ||||
| impl<F, R: Unpin> Unpin for Lazy<F, R> {} | ||||
|  | ||||
|   | ||||
| @@ -1,3 +1,12 @@ | ||||
| macro_rules! ready { | ||||
|     ($e:expr) => ( | ||||
|         match $e { | ||||
|             ::std::task::Poll::Ready(v) => v, | ||||
|             ::std::task::Poll::Pending => return ::std::task::Poll::Pending, | ||||
|         } | ||||
|     ) | ||||
| } | ||||
|  | ||||
| mod buf; | ||||
| pub(crate) mod drain; | ||||
| pub(crate) mod exec; | ||||
| @@ -10,4 +19,12 @@ pub(crate) use self::buf::StaticBuf; | ||||
| pub(crate) use self::exec::Exec; | ||||
| pub(crate) use self::lazy::{lazy, Started as Lazy}; | ||||
| pub use self::never::Never; | ||||
| pub(crate) use self::task::YieldNow; | ||||
| pub(crate) use self::task::Poll; | ||||
|  | ||||
| // group up types normally needed for `Future` | ||||
| pub(crate) use std::{ | ||||
|     future::Future, | ||||
|     marker::Unpin, | ||||
|     pin::Pin, | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -1,40 +1,10 @@ | ||||
| use futures::{Async, Poll, task::Task}; | ||||
|  | ||||
| pub(crate) use std::task::{Context, Poll}; | ||||
| use super::Never; | ||||
|  | ||||
| /// A type to help "yield" a future, such that it is re-scheduled immediately. | ||||
| /// A function to help "yield" a future, such that it is re-scheduled immediately. | ||||
| /// | ||||
| /// Useful for spin counts, so a future doesn't hog too much time. | ||||
| #[derive(Debug)] | ||||
| pub(crate) struct YieldNow { | ||||
|     cached_task: Option<Task>, | ||||
| } | ||||
|  | ||||
| impl YieldNow { | ||||
|     pub(crate) fn new() -> YieldNow { | ||||
|         YieldNow { | ||||
|             cached_task: None, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Returns `Ok(Async::NotReady)` always, while also notifying the | ||||
|     /// current task so that it is rescheduled immediately. | ||||
|     /// | ||||
|     /// Since it never returns `Async::Ready` or `Err`, those types are | ||||
|     /// set to `Never`. | ||||
|     pub(crate) fn poll_yield(&mut self) -> Poll<Never, Never> { | ||||
|         // Check for a cached `Task` first... | ||||
|         if let Some(ref t) = self.cached_task { | ||||
|             if t.will_notify_current() { | ||||
|                 t.notify(); | ||||
|                 return Ok(Async::NotReady); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // No cached task, or not current, so get a new one... | ||||
|         let t = ::futures::task::current(); | ||||
|         t.notify(); | ||||
|         self.cached_task = Some(t); | ||||
|         Ok(Async::NotReady) | ||||
|     } | ||||
| pub(crate) fn yield_now(cx: &mut Context) -> Poll<Never> { | ||||
|     cx.waker().wake_by_ref(); | ||||
|     Poll::Pending | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user