Skip to content
New issue

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

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

Already on GitHub? # to your account

🐢 Eliminate !Send resources by supporting Send and !Send World in the same binary #17667

Open
joshua-holmes opened this issue Feb 3, 2025 · 0 comments
Labels
C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled

Comments

@joshua-holmes
Copy link

joshua-holmes commented Feb 3, 2025

What problem does this solve or what need does it fill?

This issue is a replacement and extension of #17517, which attempts to solve the same problem by creating an optionally !Send World using generics. The problems with !Send resources listed in that issue are the same issues we are trying to solve here:

NonSend resources are confusing (they don't impl Resource!), badly named (#13481), require API duplication and hamper us when implementing valuable new ECS features like #17485.

That said, not everything we might want to stick in and access from the ECS is threadsafe! Audio, window handles, scripting language integrations and more are all inherently !Send. Simply removing them is not an option. Ultimately, the problem is that our model here is muddy, hampering our ability to teach, reason about and safely improve these areas of code.

Simultaneously, users have requested support for !Send components, particularly for use with web or scripting languages.

Through discussion on Discord and experimentation, we have determined that making World optionally !Send using generics is a bit messy and hacky, and we want a more long-term solution rather than a work-around.

In summary, we need to solve these problems:

  1. Eliminate !Send resources so the resources-as-components effort can be unblocked, and...
  2. Find a place to store the data from those !Send resources while still supporting their !Send status

What solution would you like?

Short term, we can replace !Send resources with thread_local!. This will unblock the resources-as-components effort. However, thread_local! requires std, which conflicts with Bevy's support for no_std, so this is not a good long-term solution.

Long term, @bushrat011899 brought up supporting both Send and !Send Worlds in the same binary. This would allow us to store the data that is currently in !Send resources in it's own !Send World as !Send components (since resources-as-components aims to remove the concept of resources altogether). If data needs to be shared from the Send World to the !Send World, @maniwani has suggested an API feature for sending functions to be run on other worlds. Usage might look something like this:

fn send_something_to_foo_world(
    mut worlds: Worlds,
    foo_world: Res<FooWorld>,
) {
    let id: WorldId = *foo_world.0;
    worlds.get_mut(id).block_on(move |mut world| {
        // Something to run on the world with non-send Foo stuff
    });
}

The long-term plan looks like this:

  1. We make non-send resources thread_local! so that resources-as-components is unblocked 🐢 Make !Send resources thread_local! #17682
  2. We add a feature flag that turns World and all of it's components into !Send, which will help on platforms that don't support multi-threading
  3. Create official support for Send and !Send World in a single binary
  4. Move thread_local! global vars into a new !Send World as !Send components

More issues will be created to break this work out further

What alternative(s) have you considered?

Some ideas we have discussed:

  1. Only officially supporting Send World (not supporting !Send World) and requiring that users store their own !Send data. However, that would come at the cost of worse UX
  2. Only supporting either a Send World or a !Send World in the same binary, but not both simultaneously and using a separate data store for !Send global data to replace our !Send resource usage. However, this would require the creation of a new !Send data store, which can be solved automatically by just creating support for Send and !Send Worlds to co-exist. Imo, it is cleaner to use a !Send World as a !Send data store and doesn't require us to re-engineer something we already have implemented. Plus having a Send and !Send World co-exist in the same binary is more dynamically useful (it's more general and has potential to be more generally useful to end users and/or other bevy teams to solve a variety of other problems).

Why 🐢 turtle emoji?

Because that's the name of the Discord work group that discusses this issue. And turtles are cute.

@joshua-holmes joshua-holmes added C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled labels Feb 3, 2025
@joshua-holmes joshua-holmes changed the title Eliminate !Send resources by supporting Send and !Send World in the same binary 🐢 Eliminate !Send resources by supporting Send and !Send World in the same binary Feb 4, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
C-Feature A new feature, making something new possible S-Needs-Triage This issue needs to be labelled
Projects
None yet
Development

No branches or pull requests

1 participant