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

macros: run current_thread inside LocalSet #4027

Merged
merged 2 commits into from
Sep 15, 2021
Merged

macros: run current_thread inside LocalSet #4027

merged 2 commits into from
Sep 15, 2021

Conversation

bnoordhuis
Copy link
Contributor

Make the "current_thread" flavor run the function body in a LocalSet so
that tokio::task::spawn_local() just works.

It's very helpful when you have hundreds of tests and don't want to
repeat the same LocalSet::new().run_until(...) stanza every time.


Aside: I ran the rustfmt --check --edition 2018 $(find . -name '*.rs' -print) command suggested in CONTRIBUTING.md but it spits out a lot of suggestions unrelated to my change. That's with rustfmt 1.4.37-stable (a178d03 2021-07-26).

Copy link
Member

@hawkw hawkw left a comment

Choose a reason for hiding this comment

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

The macro'How would you like to pay for your trip?s documentation should probably mention this behavior? Otherwise, though, this LGTM!

@bnoordhuis
Copy link
Contributor Author

Done. Thanks for the review!

@bnoordhuis
Copy link
Contributor Author

@hawkw Is there anything else I should do? Do I need to squash/rebase the commits?

@Darksonn
Copy link
Contributor

We squash on merge, so that's not necessary.

@hawkw
Copy link
Member

hawkw commented Aug 10, 2021

@hawkw Is there anything else I should do? Do I need to squash/rebase the commits?

I was just hoping to get another maintainer's opinion before going ahead and merging this one. :)

@Darksonn Darksonn added A-tokio Area: The main tokio crate M-task Module: tokio/task labels Aug 11, 2021
@Darksonn
Copy link
Contributor

One thing I wonder is that maybe it would be better to make LocalSet a new option on the builder instead of repurposing the current_thread flavor for it.

@bnoordhuis
Copy link
Contributor Author

As an unscientific data point: I did an informal "spot the bug" poll and no one (n=3) realized spawn_local() won't work without a LocalSet. Making the macros do the right thing automatically likely avoids much gnashing of teeth.

Maybe tokio::runtime::Builder::new_current_thread() should work the same way but that's probably more controversial?

@Darksonn
Copy link
Contributor

The tokio::runtime::Builder::new_current_thread() method cannot possibly work the same way because the Runtime object is Send, but a LocalSet is not.

@Darksonn
Copy link
Contributor

It is worth adding that even with the LocalSet, calling tokio::task::spawn_local() won't work inside a task spawned with tokio::spawn() as that call takes you outside the LocalSet, so you have to understand the LocalSet even if we add the LocalSet to the macro.

@bnoordhuis
Copy link
Contributor Author

7 days have passed. Is the jury verdict in?

@carllerche
Copy link
Member

It is worth adding that even with the LocalSet, calling tokio::task::spawn_local() won't work inside a task spawned with tokio::spawn() as that call takes you outside the LocalSet, so you have to understand the LocalSet even if we add the LocalSet to the macro.

It should be possible to make this work though, no?

@Darksonn
Copy link
Contributor

We discussed this on Discord. Here's a summary:

  1. Adding a LocalSet but only for the current_thread runtime is problematic because it means that spawn_local behaves differently in tests and in main.
  2. Making spawn_local work inside spawn doesn't really fix the issue because you still have this difference when the LocalSet is used with a multi-threaded runtime, so the place where it doesn't work is even more of a special case.
  3. Adding it as a new option or flavor does not help with the issue of discoverability.

I think we should change this to always adding a LocalSet, even for a multi_thread runtime. Then the behavior of spawn_local is "works in main and inside spawn_local calls, but not in tokio::spawn calls" for both main and test.

@carllerche
Copy link
Member

Discussion happened in this Discord thread (hopefully the link works)

@bnoordhuis
Copy link
Contributor Author

I'll look into making that work.

For my understanding w.r.t. to point 1: is the fear that people are going to get confused by #[tokio::main] (multi-thread) vs. #[tokio::test(flavor = "current_thread")] working differently?

#[tokio::main(flavor = "current_thread")] works like #[tokio::test(flavor = "current_thread")] with this PR. I can probably add a test to that effect, if so desired.

@Darksonn
Copy link
Contributor

Regarding point 1, the issue is that tests use the current_thread runtime by default, so they would get a LocalSet by default, whereas main would not.

@bnoordhuis
Copy link
Contributor Author

I've been going over the code and IMO there are several ways of skinning this "implicit LocalSet" cat. Can a maintainer provide some feedback on the best way forward?

My initial thinking was to:

  1. add a task::local::Context to runtime::Handle
  2. have runtime::EnterGuard activate and deactivate it (so LocalSet::run_until can still override it)

But that's probably less efficient than it could be because now more work needs to be done, plus the context must be thread-local.

@Darksonn
Copy link
Contributor

The runtime object itself is not going to have an associated LocalSet. If we do this, it would only apply to people who use the macro.

Make the #[tokio::main] and #[tokio::test] macros run the function body
in a LocalSet so that tokio::task::spawn_local() just works.

It's very helpful when you have hundreds of tests and don't want to
repeat the same LocalSet::new().run_until(...) stanza every time.
@bnoordhuis
Copy link
Contributor Author

I suppose I got confused by the discussion above but restricting it to just the macros certainly makes it easier to implement. PR updated, PTAL.

@bnoordhuis
Copy link
Contributor Author

Ping - please review?

@Darksonn
Copy link
Contributor

Darksonn commented Sep 4, 2021

I'll put it on my todolist, but I'm too tired to review anything today.

@bnoordhuis
Copy link
Contributor Author

Friendly ping.

@Darksonn
Copy link
Contributor

This is being reverted in #4142.

@bnoordhuis bnoordhuis deleted the macro-localset branch October 25, 2021 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-tokio Area: The main tokio crate M-task Module: tokio/task
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants