futures: replace pin_utils with pin_project (#374)

This allows us to remove an unnecessary clone of the dispatcher or span
from poll impls. Also, it is commonly used in other crates (e.g.
`tokio`), so might make users' dependency graphs smaller.

Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This commit is contained in:
Eliza Weisman 2019-10-05 13:51:35 -07:00 committed by GitHub
parent f7cb311df2
commit 47b6068ae9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 25 deletions

View File

@ -21,18 +21,18 @@ license = "MIT"
[features] [features]
default = ["futures-01", "tokio"] default = ["futures-01", "tokio"]
futures-01 = ["futures"] futures-01 = ["futures"]
std-future = ["pin-utils"] std-future = ["pin-project"]
futures-preview = ["std-future", "futures-core-preview"] futures-preview = ["std-future", "futures-core-preview"]
tokio-alpha = ["std-future", "tokio_02"] tokio-alpha = ["std-future", "tokio_02"]
[dependencies] [dependencies]
futures = { version = "0.1", optional = true } futures = { version = "0.1", optional = true }
futures-core-preview = { version = "0.3.0-alpha.18", optional = true } futures-core-preview = { version = "0.3.0-alpha.18", optional = true }
pin-utils = { version = "0.1.0-alpha.4", optional = true } pin-project = { version = "0.4", optional = true}
tracing = "0.1" tracing = "0.1"
tokio-executor = { version = "0.1", optional = true } tokio-executor = { version = "0.1", optional = true }
tokio = { version = "0.1", optional = true } tokio = { version = "0.1", optional = true }
tokio_02 = { package = "tokio", version = "0.2.0-alpha.4", optional = true } tokio_02 = { package = "tokio", version = "0.2.0-alpha.6", optional = true }
[dev-dependencies] [dev-dependencies]
tokio = "0.1.22" tokio = "0.1.22"

View File

@ -35,13 +35,13 @@
//! [`futures`]: https://crates.io/crates/futures //! [`futures`]: https://crates.io/crates/futures
#[cfg(feature = "futures-01")] #[cfg(feature = "futures-01")]
extern crate futures; extern crate futures;
#[cfg(feature = "std-future")]
extern crate pin_utils;
#[cfg(feature = "tokio-executor")] #[cfg(feature = "tokio-executor")]
extern crate tokio_executor; extern crate tokio_executor;
#[cfg_attr(test, macro_use)] #[cfg_attr(test, macro_use)]
extern crate tracing; extern crate tracing;
#[cfg(feature = "std-future")]
use pin_project::pin_project;
#[cfg(feature = "std-future")] #[cfg(feature = "std-future")]
use std::{pin::Pin, task::Context}; use std::{pin::Pin, task::Context};
@ -87,41 +87,44 @@ pub trait WithSubscriber: Sized {
} }
/// A future, stream, or sink that has been instrumented with a `tracing` span. /// A future, stream, or sink that has been instrumented with a `tracing` span.
#[cfg_attr(feature = "std-future", pin_project)]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Instrumented<T> { pub struct Instrumented<T> {
#[cfg(feature = "std-future")]
#[pin]
inner: T,
#[cfg(not(feature = "std-future"))]
inner: T, inner: T,
span: Span, span: Span,
} }
/// A future, stream, sink, or executor that has been instrumented with a /// A future, stream, sink, or executor that has been instrumented with a
/// `tracing` subscriber. /// `tracing` subscriber.
#[cfg_attr(feature = "std-future", pin_project)]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct WithDispatch<T> { pub struct WithDispatch<T> {
// cfg_attr doesn't work inside structs, apparently...
#[cfg(feature = "std-future")]
#[pin]
inner: T,
#[cfg(not(feature = "std-future"))]
inner: T, inner: T,
dispatch: Dispatch, dispatch: Dispatch,
} }
impl<T: Sized> Instrument for T {} impl<T: Sized> Instrument for T {}
#[cfg(feature = "std-future")]
impl<T: std::future::Future> Instrumented<T> {
pin_utils::unsafe_pinned!(inner: T);
}
#[cfg(feature = "std-future")] #[cfg(feature = "std-future")]
impl<T: std::future::Future> std::future::Future for Instrumented<T> { impl<T: std::future::Future> std::future::Future for Instrumented<T> {
type Output = T::Output; type Output = T::Output;
fn poll(mut self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context) -> std::task::Poll<Self::Output> {
let span = self.as_ref().span.clone(); let this = self.project();
let _enter = span.enter(); let _enter = this.span.enter();
self.as_mut().inner().poll(lw) this.inner.poll(cx)
} }
} }
#[cfg(feature = "std-future")]
impl<T: Unpin> Unpin for Instrumented<T> {}
#[cfg(feature = "futures-01")] #[cfg(feature = "futures-01")]
impl<T: futures::Future> futures::Future for Instrumented<T> { impl<T: futures::Future> futures::Future for Instrumented<T> {
type Item = T::Item; type Item = T::Item;
@ -192,18 +195,15 @@ impl<T: futures::Future> futures::Future for WithDispatch<T> {
} }
} }
#[cfg(feature = "std-future")]
impl<T: std::future::Future> WithDispatch<T> {
pin_utils::unsafe_pinned!(inner: T);
}
#[cfg(feature = "std-future")] #[cfg(feature = "std-future")]
impl<T: std::future::Future> std::future::Future for WithDispatch<T> { impl<T: std::future::Future> std::future::Future for WithDispatch<T> {
type Output = T::Output; type Output = T::Output;
fn poll(mut self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context) -> std::task::Poll<Self::Output> {
let dispatch = self.as_ref().dispatch.clone(); let this = self.project();
dispatcher::with_default(&dispatch, || self.as_mut().inner().poll(lw)) let dispatch = this.dispatch;
let future = this.inner;
dispatcher::with_default(dispatch, || future.poll(cx))
} }
} }