Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limit futures dependency to Stream via feature flag #1774

Merged
merged 15 commits into from
Nov 16, 2019
Merged

Conversation

carllerche
Copy link
Member

@carllerche carllerche commented Nov 15, 2019

In an effort to reach API stability, the tokio crate is shedding its
public dependencies on crates that are either a) do not provide a
stable (1.0+) release with longevity guarantees or b) match the tokio
release cadence. Of course, implementing std traits fits the
requirements.

The on exception, for now, is the Stream trait found in futures_core.
It is expected that this trait will not change much and be moved into `std.
Since Tokio is not yet going reaching 1.0, I feel that it is acceptable to maintain
a dependency on this trait given how foundational it is.

Since the Stream implementation is optional, types that are logically
streams provide async fn next_* functions to obtain the next value.
Avoiding the next() name prevents fn conflicts with StreamExt::next().

Additionally, some misc cleanup is also done:

  • tokio::io::io -> tokio::io::util.
  • delay -> delay_until.
  • Timeout::new -> timeout(...).
  • signal::ctrl_c() returns a future instead of a stream.
  • {tcp,unix}::Incoming is removed (due to lack of Stream trait).
  • time::Throttle is removed (due to lack of Stream trait).
  • Fix: mpsc::UnboundedSender::send(&self) (no more conflict with Sink fns).

In an effort to reach API stability, the `tokio` crate is shedding its
_public_ dependencies on crates that are either a) do not provide a
stable (1.0+) release with longevity guarantees or b) match the `tokio`
release cadence. Of course, implmementing `std` traits fits the
requirements.

Instead of publically dependending on `futures` from `tokio`, the
`tokio-util` crate provides the necessary bridge to go from Tokio types
to `futures` traits (primarily `Stream`).

Instead of implementing `Stream` for iteration, types that are logically
streams provide `async fn next_*` functions to obtain the next value.
Avoiding the `next()` function name will allow for forwards
compatibility once the `Stream` trait is provided by `std`.

Additionally, some misc cleanup is also done:

- `tokio::io::io` -> `tokio::io::util`.
- `delay` -> `delay_until`.
- `Timeout::new` -> `timeout(...)`.
- `signal::ctrl_c()` returns a future instead of a stream.
- `{tcp,unix}::Incoming` is removed (due to lack of `Stream` trait).
- `time::Throttle` is removed (due to lack of `Stream` trait).
@ipetkov
Copy link
Member

ipetkov commented Nov 15, 2019

The signal and process changes LGTM, modulo adding docs on the Signal impl methods!

@taiki-e
Copy link
Member

taiki-e commented Nov 15, 2019

Any reason for choosing to define our own trait instead of depends on futures via feature flags?

tokio/src/stream/mod.rs Outdated Show resolved Hide resolved
@vorot93
Copy link
Member

vorot93 commented Nov 15, 2019

Even though I do understand the reasoning behind this move, it's nevertheless not easy to accept as it kind of feels like forced reinventing the wheel. After all, is Stream trait really going to undergo a breaking change in the future?

tokio-util/src/stream/mod.rs Outdated Show resolved Hide resolved
tokio-util/src/stream/into_std.rs Outdated Show resolved Hide resolved
@carllerche
Copy link
Member Author

After some discussion in discord: Tokio's next release isn't 1.0, so we can pull in futures-core via a feature flag and hopefully Stream will be stabilized before 1.0.

@carllerche
Copy link
Member Author

Ok, based on feedback, I brought back a futures_core::Stream dependency behind a stream feature flag.

@carllerche
Copy link
Member Author

@ipetkov which fns?

@seanmonstar
Copy link
Member

There's one (big) concern with an unstable feature flag: other dependencies can enable it, and a user doesn't realize they are using "unstable" APIs. This problem was noticed in Rayon, and they switched from an unstable feature to requiring RUSTFLAGS="--cfg rayon_unstable" instead.

I've also noticed that warp master is depending on hyper's unstable-stream feature, which means anyone who uses warp and hyper will notice the "unstable" APIs are just available, like Body::wrap_stream.

@carllerche
Copy link
Member Author

I agree that unstable feature flags aren’t a viable option.

Since we aren’t hitting 1.0 and there is a path for Stream to land in std by 1.0 I say we stay optimistic

@@ -122,7 +122,7 @@ impl Handle {
/// The next operation in the mock's script will be to expect a `read` call
/// and return `buf`.
pub fn read(&mut self, buf: &[u8]) -> &mut Self {
self.tx.try_send(Action::Read(buf.into())).unwrap();
self.tx.send(Action::Read(buf.into())).unwrap();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unbounded mpsc send API changed to be more ergonomic.

@@ -524,7 +524,7 @@ async fn client_to_server() {
drop(env_logger::try_init());

// Create a server listening on a port, then figure out what that port is
let srv = t!(TcpListener::bind("127.0.0.1:0").await);
let mut srv = t!(TcpListener::bind("127.0.0.1:0").await);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

incoming now takes &mut self.

@carllerche carllerche changed the title remove futures dependency from tokio Limit futures dependency to Stream via feature flag Nov 15, 2019
@@ -298,7 +298,7 @@ impl AsyncRead for Mock {
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => {
if let Some(rem) = self.inner.remaining_wait() {
let until = Instant::now() + rem;
self.inner.sleep = Some(time::delay(until));
self.inner.sleep = Some(time::delay_until(until));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delay was renamed delay_until to further disambiguate from delay_for.

@@ -40,7 +41,7 @@ blocking = ["rt-core"]
dns = ["blocking"]
fs = ["blocking"]
io-driver = ["mio", "lazy_static", "sync"] # TODO: get rid of sync
io-util = ["pin-project", "memchr"]
io-util = ["pin-project", "pin-project-lite", "memchr"]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying out pin-project-lite, we probably should switch.

iovec = "0.1"

# Everything else is optional...
fnv = { version = "1.0.6", optional = true }
futures-core = { version = "0.3.0", optional = true }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only the Stream trait is used.


/// A future that may have completed.
#[derive(Debug)]
pub(crate) enum MaybeDone<Fut: Future> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of dealing w/ refactoring internals to remove dependency on the few futures-util helpers, I copied them here as a temporary measure.

@@ -0,0 +1,15 @@
#![allow(unused_imports, dead_code)]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really feel like figuring out which feature flags need which helpers. I hope that some of these can be removed.

#[cfg(feature = "io-util")]
pub use self::io::{
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move files from tokio::io::io -> tokio::io::util.

@@ -0,0 +1,44 @@
use std::future::Future;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this file is unused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants