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

Add no_std support to bevy_tasks #15464

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

bushrat011899
Copy link
Contributor

@bushrat011899 bushrat011899 commented Sep 27, 2024

Objective

Solution

  • Added std feature (enabled by default)
  • Replaced reliance on async-executor dependency with an in-tree alternative based on said dependency.
  • Updated the single_threaded_task_pool to work in no_std environments by gating its reliance on thread_local.

Testing

  • Ran CI locally.
  • cargo clippy -p bevy_tasks --target "x86_64-unknown-none" --no-default-features

Notes

  • The file executor.rs is heavily inspired by async-executor's lib.rs. Comparing to the source may help with understanding what changes needed to be made for no_std compatibility.
  • Because we don't have access to thread_local in no_std, we cannot guarantee access to LOCAL_EXECUTOR is within the same thread. This is why in no_std, there is a stricter requirement on tasks to be Send and possibly Sync. These cases are annotated with MaybeSync and MaybeSend bounds.
  • This PR is blocked until Minor fixes for bevy_utils in no_std #15463 is merged, as bevy_utils needs to successfully compile in no_std contexts for bevy_tasks to also compile successfully.

`thread_local`, `getrandom`, and `web-time` were being included even in `no_std` configurations. Additionally, `hashbrown` had extra features enabled that should've been gated.
@bushrat011899 bushrat011899 added C-Feature A new feature, making something new possible S-Blocked This cannot move forward until something else changes A-Tasks Tools for parallel and async work D-Straightforward Simple bug fixes and API improvements, docs, test and examples D-Async Deals with asynchronous abstractions labels Sep 27, 2024
@bushrat011899 bushrat011899 added the X-Controversial There is active debate or serious implications around merging this PR label Sep 27, 2024
@hymm
Copy link
Contributor

hymm commented Sep 27, 2024

Is it possible to try and upstream the no_std changes to async executor? I'm not sure bevy wants to pick which executor to use yet. See #6762 or #11995. If we do want to do this, we shouldn't just copy the code, but tests, benches, and CI too. (This would probably be a separate PR for ease of review.)

Copy link
Contributor

@BenjaminBrienen BenjaminBrienen left a comment

Choose a reason for hiding this comment

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

Awesome. Very clean.

@bushrat011899
Copy link
Contributor Author

Is it possible to try and upstream the no_std changes to async executor?

It might be possible! The reason I didn't start there is the crate describes itself as a reference implementation, and that you should write your own executor using the underlying async-tasks crate instead.

I'm not sure bevy wants to pick which executor to use yet. See #6762 or #11995. If we do want to do this, we shouldn't just copy the code, but tests, benches, and CI too. (This would probably be a separate PR for ease of review.)

Perfectly reasonable! I've copied over all the tests as well (this executor was only a single file), but I do agree that something like Tokio or Rayon could also work. But, I specifically just want to get no_std support over the line, and those crates aren't no_std.

Copy link
Contributor

@BenjaminBrienen BenjaminBrienen left a comment

Choose a reason for hiding this comment

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

Still good

@bushrat011899 bushrat011899 added S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed S-Blocked This cannot move forward until something else changes labels Oct 9, 2024
@bushrat011899 bushrat011899 added this to the 0.16 milestone Oct 10, 2024
@hymm
Copy link
Contributor

hymm commented Nov 4, 2024

I've copied over all the tests as well (this executor was only a single file.

Tests are actually here: https://github.com/smol-rs/async-executor/tree/master/tests. The async-executor repo also runs loom on the tests. If this is merged we should figure out how to run loom on bevy_tasks.

But I'm really not sure if forking async executor is worth it just for no-std support. We're potentially locking bevy out from future upstream improvements. For consoles I imagine that they'll need to have their own fork of async executor anyways as they should be able to park and unpark threads, so would be able to have their own Mutex implementation, which would be better than spin locking. If no_std is only single threaded is there a different async executor we can use and then have a separate no_std task pool?

@bushrat011899 bushrat011899 added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged and removed S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Nov 4, 2024
@bushrat011899
Copy link
Contributor Author

I've copied over all the tests as well (this executor was only a single file.

Tests are actually here: https://github.com/smol-rs/async-executor/tree/master/tests. The async-executor repo also runs loom on the tests. If this is merged we should figure out how to run loom on bevy_tasks.

Thanks for pointing that out, not sure how I missed it! So used to having unit tests within the same file I got complacent.

But I'm really not sure if forking async executor is worth it just for no-std support. We're potentially locking bevy out from future upstream improvements. For consoles I imagine that they'll need to have their own fork of async executor anyways as they should be able to park and unpark threads, so would be able to have their own Mutex implementation, which would be better than spin locking. If no_std is only single threaded is there a different async executor we can use and then have a separate no_std task pool?

These are excellent points and I generally agree. There was some discussion in the Discord around potentially using embassy as a way to bring multi-threaded executor support anyway. I think I will update this PR to continue using async-executor for std targets (behind a default feature flag) and pivot the forked implementation to just be for no_std where embassy couldn't be used (very basic single-threaded only). As a follow-up PR, multi-threaded support could then be added via something like embassy (behind a non-default feature flag).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Tasks Tools for parallel and async work C-Feature A new feature, making something new possible D-Async Deals with asynchronous abstractions D-Straightforward Simple bug fixes and API improvements, docs, test and examples S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged X-Controversial There is active debate or serious implications around merging this PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants