Skip to content

Commit b720bd9

Browse files
committed
futures: support std::futures::Future with !Unpin futures
- Thank you Eliza Weisman (hawkw) for the solution using the pin-utils crate - Added feature gates for the futures 0.1, tokio, and std::future implementations
1 parent 63d8516 commit b720bd9

File tree

3 files changed

+60
-23
lines changed

3 files changed

+60
-23
lines changed

tracing-futures/Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@ authors = ["Eliza Weisman <[email protected]>"]
55
edition = "2018"
66

77
[features]
8-
default = ["tokio"]
8+
default = ["futures-01", "tokio"]
9+
futures-01 = ["futures"]
10+
std-future = ["pin-utils"]
911

1012
[dependencies]
11-
futures = "0.1"
13+
futures = { version = "0.1", optional = true }
14+
pin-utils = { version = "0.1.0-alpha.4", optional = true }
1215
tracing = "0.1"
1316
tokio = { version = "0.1", optional = true }
1417
tokio-executor = { version = "0.1", optional = true }

tracing-futures/src/executor.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
use crate::{Instrument, Instrumented, WithDispatch};
2+
#[cfg(feature = "futures-01")]
23
use futures::{
3-
future::{ExecuteError, Executor},
4-
Future,
5-
};
6-
7-
#[cfg(feature = "tokio")]
8-
use tokio::{
9-
executor::{Executor as TokioExecutor, SpawnError},
10-
runtime::{current_thread, Runtime, TaskExecutor},
4+
future::{ExecuteError, Executor},
5+
Future,
116
};
7+
#[cfg(feature = "futures-01")]
8+
use tokio::executor::{Executor as TokioExecutor, SpawnError};
9+
use tokio::runtime::{current_thread, Runtime, TaskExecutor};
1210

11+
#[cfg(feature = "futures-01")]
1312
macro_rules! deinstrument_err {
1413
($e:expr) => {
1514
$e.map_err(|e| {
@@ -20,6 +19,7 @@ macro_rules! deinstrument_err {
2019
};
2120
}
2221

22+
#[cfg(feature = "futures-01")]
2323
impl<T, F> Executor<F> for Instrumented<T>
2424
where
2525
T: Executor<Instrumented<F>>,
@@ -31,7 +31,7 @@ where
3131
}
3232
}
3333

34-
#[cfg(feature = "tokio")]
34+
#[cfg(all(feature = "futures-01", feature = "tokio"))]
3535
impl<T> TokioExecutor for Instrumented<T>
3636
where
3737
T: TokioExecutor,
@@ -56,6 +56,7 @@ impl Instrumented<Runtime> {
5656
///
5757
/// This method simply wraps a call to `tokio::runtime::Runtime::spawn`,
5858
/// instrumenting the spawned future beforehand.
59+
#[cfg(feature = "futures-01")]
5960
pub fn spawn<F>(&mut self, future: F) -> &mut Self
6061
where
6162
F: Future<Item = (), Error = ()> + Send + 'static,
@@ -80,6 +81,7 @@ impl Instrumented<Runtime> {
8081
///
8182
/// This function panics if the executor is at capacity, if the provided
8283
/// future panics, or if called within an asynchronous execution context.
84+
#[cfg(feature = "futures-01")]
8385
pub fn block_on<F, R, E>(&mut self, future: F) -> Result<R, E>
8486
where
8587
F: Send + 'static + Future<Item = R, Error = E>,
@@ -108,6 +110,7 @@ impl Instrumented<current_thread::Runtime> {
108110
///
109111
/// This method simply wraps a call to `current_thread::Runtime::spawn`,
110112
/// instrumenting the spawned future beforehand.
113+
#[cfg(feature = "futures-01")]
111114
pub fn spawn<F>(&mut self, future: F) -> &mut Self
112115
where
113116
F: Future<Item = (), Error = ()> + 'static,
@@ -141,6 +144,7 @@ impl Instrumented<current_thread::Runtime> {
141144
///
142145
/// This function panics if the executor is at capacity, if the provided
143146
/// future panics, or if called within an asynchronous execution context.
147+
#[cfg(feature = "futures-01")]
144148
pub fn block_on<F, R, E>(&mut self, future: F) -> Result<R, E>
145149
where
146150
F: 'static + Future<Item = R, Error = E>,
@@ -165,6 +169,7 @@ impl Instrumented<current_thread::Runtime> {
165169
}
166170
}
167171

172+
#[cfg(feature = "futures-01")]
168173
impl<T, F> Executor<F> for WithDispatch<T>
169174
where
170175
T: Executor<WithDispatch<F>>,
@@ -176,7 +181,7 @@ where
176181
}
177182
}
178183

179-
#[cfg(feature = "tokio")]
184+
#[cfg(all(feature = "futures-01", feature = "tokio"))]
180185
impl<T> TokioExecutor for WithDispatch<T>
181186
where
182187
T: TokioExecutor,
@@ -202,6 +207,7 @@ impl WithDispatch<Runtime> {
202207
///
203208
/// This method simply wraps a call to `tokio::runtime::Runtime::spawn`,
204209
/// instrumenting the spawned future beforehand.
210+
#[cfg(feature = "futures-01")]
205211
pub fn spawn<F>(&mut self, future: F) -> &mut Self
206212
where
207213
F: Future<Item = (), Error = ()> + Send + 'static,
@@ -227,6 +233,7 @@ impl WithDispatch<Runtime> {
227233
///
228234
/// This function panics if the executor is at capacity, if the provided
229235
/// future panics, or if called within an asynchronous execution context.
236+
#[cfg(feature = "futures-01")]
230237
pub fn block_on<F, R, E>(&mut self, future: F) -> Result<R, E>
231238
where
232239
F: Send + 'static + Future<Item = R, Error = E>,
@@ -257,6 +264,7 @@ impl WithDispatch<current_thread::Runtime> {
257264
///
258265
/// This method simply wraps a call to `current_thread::Runtime::spawn`,
259266
/// instrumenting the spawned future beforehand.
267+
#[cfg(feature = "futures-01")]
260268
pub fn spawn<F>(&mut self, future: F) -> &mut Self
261269
where
262270
F: Future<Item = (), Error = ()> + 'static,
@@ -290,6 +298,7 @@ impl WithDispatch<current_thread::Runtime> {
290298
///
291299
/// This function panics if the executor is at capacity, if the provided
292300
/// future panics, or if called within an asynchronous execution context.
301+
#[cfg(feature = "futures-01")]
293302
pub fn block_on<F, R, E>(&mut self, future: F) -> Result<R, E>
294303
where
295304
F: 'static + Future<Item = R, Error = E>,

tracing-futures/src/lib.rs

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,37 @@
1414
//!
1515
//! [`Instrument`]: trait.Instrument.html
1616
//! [`WithSubscriber`]: trait.WithSubscriber.html
17+
#[cfg(feature = "futures-01")]
1718
extern crate futures;
19+
#[cfg(feature = "std-future")]
20+
extern crate pin_utils;
1821
#[cfg(feature = "tokio")]
1922
extern crate tokio;
2023
#[cfg(feature = "tokio-executor")]
2124
extern crate tokio_executor;
2225
#[cfg_attr(test, macro_use)]
2326
extern crate tracing;
2427

28+
#[cfg(feature = "std-future")]
2529
use std::{
2630
pin::Pin,
2731
task::Context,
2832
};
2933

34+
#[cfg(feature = "futures-01")]
3035
use futures::{Sink, StartSend, Stream};
31-
use tracing::{dispatcher, Dispatch, Span};
36+
#[cfg(feature = "futures-01")]
37+
use tracing::dispatcher;
38+
use tracing::{Dispatch, Span};
3239

40+
#[cfg(feature = "tokio")]
3341
pub mod executor;
3442

3543
// TODO: seal?
3644
pub trait Instrument: Sized {
3745
fn instrument(self, span: Span) -> Instrumented<Self> {
3846
Instrumented { inner: self, span }
3947
}
40-
41-
fn boxed_instrument(self, span: Span) -> Instrumented<Pin<Box<Self>>> {
42-
Instrumented { inner: Box::pin(self), span }
43-
}
4448
}
4549

4650
pub trait WithSubscriber: Sized {
@@ -69,16 +73,26 @@ pub struct WithDispatch<T> {
6973

7074
impl<T: Sized> Instrument for T {}
7175

72-
impl<P: std::future::Future + Unpin> std::future::Future for Instrumented<P> {
73-
type Output = P::Output;
76+
#[cfg(feature = "std-future")]
77+
impl<T: std::future::Future> Instrumented<T> {
78+
pin_utils::unsafe_pinned!(inner: T);
79+
}
7480

75-
fn poll(self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll<Self::Output> {
76-
let this = self.get_mut();
77-
let _enter = this.span.enter();
78-
Pin::new(&mut this.inner).poll(lw)
81+
#[cfg(feature = "std-future")]
82+
impl<T: std::future::Future> std::future::Future for Instrumented<T> {
83+
type Output = T::Output;
84+
85+
fn poll(mut self: Pin<&mut Self>, lw: &mut Context) -> std::task::Poll<Self::Output> {
86+
let span = self.as_ref().span.clone();
87+
let _enter = span.enter();
88+
self.as_mut().inner().poll(lw)
7989
}
8090
}
8191

92+
#[cfg(feature = "std-future")]
93+
impl<T: Unpin> Unpin for Instrumented<T> {}
94+
95+
#[cfg(feature = "futures-01")]
8296
impl<T: futures::Future> futures::Future for Instrumented<T> {
8397
type Item = T::Item;
8498
type Error = T::Error;
@@ -89,6 +103,7 @@ impl<T: futures::Future> futures::Future for Instrumented<T> {
89103
}
90104
}
91105

106+
#[cfg(feature = "futures-01")]
92107
impl<T: Stream> Stream for Instrumented<T> {
93108
type Item = T::Item;
94109
type Error = T::Error;
@@ -99,6 +114,7 @@ impl<T: Stream> Stream for Instrumented<T> {
99114
}
100115
}
101116

117+
#[cfg(feature = "futures-01")]
102118
impl<T: Sink> Sink for Instrumented<T> {
103119
type SinkItem = T::SinkItem;
104120
type SinkError = T::SinkError;
@@ -135,6 +151,7 @@ impl<T> Instrumented<T> {
135151

136152
impl<T: Sized> WithSubscriber for T {}
137153

154+
#[cfg(feature = "futures-01")]
138155
impl<T: futures::Future> futures::Future for WithDispatch<T> {
139156
type Item = T::Item;
140157
type Error = T::Error;
@@ -146,6 +163,7 @@ impl<T: futures::Future> futures::Future for WithDispatch<T> {
146163
}
147164

148165
impl<T> WithDispatch<T> {
166+
#[cfg(feature = "tokio")]
149167
pub(crate) fn with_dispatch<U: Sized>(&self, inner: U) -> WithDispatch<U> {
150168
WithDispatch {
151169
dispatch: self.dispatch.clone(),
@@ -176,6 +194,8 @@ mod tests {
176194
extern crate tokio;
177195

178196
use super::{test_support::*, *};
197+
198+
#[cfg(feature = "futures-01")]
179199
use futures::{future, stream, task, Async, Future};
180200
use tracing::{subscriber::with_default, Level};
181201

@@ -185,6 +205,7 @@ mod tests {
185205
polls: usize,
186206
}
187207

208+
#[cfg(feature = "futures-01")]
188209
impl<T, E> futures::Future for PollN<T, E> {
189210
type Item = T;
190211
type Error = E;
@@ -220,6 +241,7 @@ mod tests {
220241
}
221242
}
222243

244+
#[cfg(feature = "futures-01")]
223245
#[test]
224246
fn future_enter_exit_is_reasonable() {
225247
let (subscriber, handle) = subscriber::mock()
@@ -239,6 +261,7 @@ mod tests {
239261
handle.assert_finished();
240262
}
241263

264+
#[cfg(feature = "futures-01")]
242265
#[test]
243266
fn future_error_ends_span() {
244267
let (subscriber, handle) = subscriber::mock()
@@ -259,6 +282,7 @@ mod tests {
259282
handle.assert_finished();
260283
}
261284

285+
#[cfg(feature = "futures-01")]
262286
#[test]
263287
fn stream_enter_exit_is_reasonable() {
264288
let (subscriber, handle) = subscriber::mock()
@@ -282,6 +306,7 @@ mod tests {
282306
handle.assert_finished();
283307
}
284308

309+
#[cfg(feature = "futures-01")]
285310
#[test]
286311
fn span_follows_future_onto_threadpool() {
287312
let (subscriber, handle) = subscriber::mock()

0 commit comments

Comments
 (0)