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

util/io: Add SyncIoBridge #4146

Merged
merged 14 commits into from Oct 22, 2021
Merged

util/io: Add SyncIoBridge #4146

merged 14 commits into from Oct 22, 2021

Conversation

cgwalters
Copy link
Contributor

Motivation

I'm doing quite a bit of stuff inside spawn_blocking because
I need to use some large synchronous APIs.

I found it not entirely obvious how to "bridge" the world of
async I/O with sync I/O.

Since we have a handy "tokio-util" module with an "io" feature,
these small helpers seem like a good fit hopefully!

Solution

Extracted these from my code in https://github.com/ostreedev/ostree-rs-ext/blob/main/lib/src/async_util.rs

@Darksonn Darksonn added A-tokio-util Area: The tokio-util crate M-io Module: tokio/io labels Oct 2, 2021
Copy link
Contributor

@Darksonn Darksonn left a comment

Choose a reason for hiding this comment

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

Why not create a single type with both impls? Then it is easier to bridge a type with both traits.

tokio-util/src/io/sync_bridge.rs Outdated Show resolved Hide resolved
@cgwalters
Copy link
Contributor Author

Why not create a single type with both impls? Then it is easier to bridge a type with both traits.

Good suggestion, done!

@cgwalters cgwalters force-pushed the sync-io-bridge branch 2 times, most recently from e3bef63 to 913b94e Compare October 3, 2021 13:53
tokio-util/src/io/sync_bridge.rs Outdated Show resolved Hide resolved
/// Use a [`tokio::io::AsyncRead`] synchronously as a [`std::io::Read`] or
/// a [`tokio::io::AsyncWrite`] as a [`std::io::Write`].
#[derive(Debug)]
pub struct SyncIOBridge<T> {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: in general, idiomatic Rust naming treats acronyms (like "IO") as one "word", rather than capitalizing every letter: https://doc.rust-lang.org/1.0.0/style/style/naming/README.html#general-conventions-[rfc-#430]

So, this should be

Suggested change
pub struct SyncIOBridge<T> {
pub struct SyncIoBridge<T> {

Copy link
Member

Choose a reason for hiding this comment

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

also, take it or leave it, but we could probably just drop the Io from the name of this, since it's already in the io module? i'm fine either way though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I was uncertain about the Io. What makes me lean towards leaving it in is that there's also e.g. the whole tokio::sync module which is about synchronization as opposed to "synchronous". I don't expect this type to be frequently used, and it's probably worth being a bit more verbose to highlight the conversion? But if someone feels strongly I'm obviously fine changing!

Maybe we could use the term "blocking", e.g. BlockingIoWrapper?

Or actually, there's already some precendent in tokio for from_std so we could call it StdIoWrapper (or StdIoBridge)?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think Blocking or Sync is better than Std here. I don't particularly mind including Io in the name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK...keeping this as SyncIoBridge then just from inertia basically. But happy to change if someone else feels strongly.

tokio-util/src/io/sync_bridge.rs Outdated Show resolved Hide resolved
tokio-util/src/io/mod.rs Outdated Show resolved Hide resolved
tokio-util/src/io/sync_bridge.rs Show resolved Hide resolved
@cgwalters cgwalters force-pushed the sync-io-bridge branch 2 times, most recently from 15d2f0a to e729ec2 Compare October 3, 2021 18:23
cgwalters added a commit to cgwalters/tokio that referenced this pull request Oct 4, 2021
I'm working on some code which heavily uses `spawn_blocking`
to run synchronous code, and it took me a while to find and understand
the relevant APIs and patterns here.  Let's link to the channel
blocking APIs, and provide a small example.

I plan to mention tokio-rs#4146 here
too once that merges.
cgwalters added a commit to cgwalters/tokio that referenced this pull request Oct 4, 2021
I'm working on some code which heavily uses `spawn_blocking`
to run synchronous code, and it took me a while to find and understand
the relevant APIs and patterns here.  Let's link to the channel
blocking APIs, and provide a small example.

I plan to mention tokio-rs#4146 here
too once that merges.
@cgwalters cgwalters force-pushed the sync-io-bridge branch 2 times, most recently from cb4f217 to c5f145d Compare October 4, 2021 13:38
tokio-util/src/io/sync_bridge.rs Outdated Show resolved Hide resolved
tokio-util/src/io/sync_bridge.rs Show resolved Hide resolved
tokio-util/src/io/sync_bridge.rs Outdated Show resolved Hide resolved
@Darksonn
Copy link
Contributor

Darksonn commented Oct 4, 2021

When you make changes to this PR, please avoid force pushing as it makes it difficult for me to see what changed since last time I looked. Do not worry about there being lots of commits — they will be squashed when we merge the PR.

@cgwalters
Copy link
Contributor Author

When you make changes to this PR, please avoid force pushing as it makes it difficult for me to see what changed since last time I looked.

OK, though I think I had some local changes before I saw this, so there is a final force here, but subsequent update commits.
(That said, github does have a minimal interdiff view).

@Darksonn
Copy link
Contributor

Darksonn commented Oct 5, 2021

The CI failure is due to you being very far behind the master branch.

I'm doing quite a bit of stuff inside `spawn_blocking` because
I need to use some large synchronous APIs.

I found it not entirely obvious how to "bridge" the world of
async I/O with sync I/O.

Since we have a handy "tokio-util" module with an "io" feature,
these small helpers seem like a good fit hopefully!

Extracted these from my code in https://github.com/ostreedev/ostree-rs-ext/blob/main/lib/src/async_util.rs
@cgwalters
Copy link
Contributor Author

Rebased 🏄

@cgwalters
Copy link
Contributor Author

cgwalters commented Oct 20, 2021

(This is really the first time I've tried to debug issues in a multi-crate git repository with crosscutting features)

OK, I was misreading the CI before, at least one failure reproduces here with: cargo +nightly check -Z avoid-dev-deps --no-default-features --features full.

I initially tried sprinkling cfg_io! etc. in different places, but that didn't work. It took me a little while to realize I was getting confused between the tokio io-util feature and the tokio-util io feature. And here, we really need to require the tokio feature (right?).

So this fixes it for me:

diff --git a/tokio-util/Cargo.toml b/tokio-util/Cargo.toml
index 8c0481ec..f81734b3 100644
--- a/tokio-util/Cargo.toml
+++ b/tokio-util/Cargo.toml
@@ -35,7 +35,7 @@ rt = ["tokio/rt"]
 __docs_rs = ["futures-util"]
 
 [dependencies]
-tokio = { version = "1.0.0", path = "../tokio", features = ["sync"] }
+tokio = { version = "1.0.0", path = "../tokio", features = ["sync", "io-util"] }
 
 bytes = "1.0.0"
 futures-core = "0.3.0"

but would that be OK? Or would it be necessary to add a new tokio-util feature that in turn enables the io-util tokio feature?

@Darksonn
Copy link
Contributor

We could add an io-util feature to tokio-util that enables the io-util feature of Tokio.

Necessary for the sync bridge work.  I don't know
whether this is OK.
@cgwalters
Copy link
Contributor Author

Now that I looked it is easier, we just need to have the tokio-util/io feature depend on tokio/io-util (the terms here are confusing!)

We could add an io-util feature to tokio-util that enables the io-util feature of Tokio.

That said, happy to do that instead if the tokio/io-util feature is potentially problematic for users of tokio-util/io. I honestly do not have a strong sense of which tokio users are selecting which features. The depchain of tokio/io-util seems like it's just ['memchr', 'bytes'] and tokio-util already hard depends on bytes, so after this change, requesting tokio-util/io now just pulls in memchr or so which seems quite small.

@cgwalters
Copy link
Contributor Author

Ahh. Right, we also need rt. Hmm, I think that's going to force us to go to the separate tokio-util/io-util feature route?

tokio-util/Cargo.toml Outdated Show resolved Hide resolved
Co-authored-by: Alice Ryhl <aliceryhl@google.com>
@Darksonn
Copy link
Contributor

If CI keeps failing for unrelated reasons, you may want to merge in master to your PR.

@Darksonn
Copy link
Contributor

I figured out what the problem is. #4189

@cgwalters
Copy link
Contributor Author

I figured out what the problem is. #4189

Ah nice, thanks.

Copy link
Contributor

@Darksonn Darksonn left a comment

Choose a reason for hiding this comment

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

This seems good!

@Darksonn Darksonn merged commit 2734fa9 into tokio-rs:master Oct 22, 2021
@Darksonn
Copy link
Contributor

If you want, you could amend the Bridging with sync code topics page with a section on this utility.

@cgwalters
Copy link
Contributor Author

If you want, you could amend the Bridging with sync code topics page with a section on this utility.

Oh wow, I somehow completely missed that before. Should I update #4150 to link to that too?

@Darksonn
Copy link
Contributor

Sure.

cgwalters added a commit to cgwalters/ostree-rs-ext that referenced this pull request Oct 26, 2021
We can only land this after a new tokio is released with
tokio-rs/tokio#4146
@cgwalters
Copy link
Contributor Author

xref #4150 (comment)

oliver-giersch pushed a commit to oliver-giersch/tokio that referenced this pull request Oct 28, 2021
cgwalters added a commit to cgwalters/ostree-rs-ext that referenced this pull request Oct 30, 2021
We can only land this after a new tokio is released with
tokio-rs/tokio#4146
@cgwalters
Copy link
Contributor Author

From time to time I like to explicitly say "thank you" in a Github comment. A lot of time Github conversations can be about bug reports, people upset about regressions, contentious debates, etc.

This was my first real PR to this repository and you all took the time to work with me, patiently found issues and help me learn new things, and it was overall a great experience. It definitely led to me feeling positive about contributing to tokio again!

So: thank you! 🙏

@Darksonn
Copy link
Contributor

That's great! I'm happy that you found it to be a good experience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio-util Area: The tokio-util crate M-io Module: tokio/io
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants