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

Configurable Events<T> storage #2073

Closed

Conversation

TheRawMeatball
Copy link
Member

Solves #2071


pub trait Storage<'a> {
type Item: 'a;
type DrainIter: DoubleEndedIterator<Item = Self::Item> + 'a;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it worth loosening this requirement from just DoubleEndedIterators?
If we're now allowing custom storage types for Events, we should maybe support more than just these types.
For example, if I don't want any duplicate events, I may want to make a Storage type which uses a HashSet internally, but hash_set::Iter does not implement DoubleEndedIter.

Copy link
Member Author

Choose a reason for hiding this comment

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

This trait is a mostly internal trait, which isn't meant to be implemented. HashSet would also fail because it doesn't match the Deref<[_]> criteria.

@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible labels May 1, 2021
@TheRawMeatball
Copy link
Member Author

Blocked on #2074

Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

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

This is great functionality, and the code quality looks good. It could just use slightly more than 0 documentation about how to use it <3

@@ -12,6 +12,8 @@ fn main() {
.run();
}

#[derive(Event)]
#[store(3)]
Copy link
Member

Choose a reason for hiding this comment

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

This needs a comment explaining what it does and why you might want to use it ;)

@mockersf
Copy link
Member

mockersf commented May 3, 2021

too bad events would need to #[derive(Event)] 😞

@alice-i-cecile
Copy link
Member

too bad events would need to #[derive(Event)] 😞

On the plus side, this will make me feel much more confident in excluding "Event" from all of my event types :p It should also allow us to extend the API further / increase clarity further elsewhere.

@cart
Copy link
Member

cart commented May 5, 2021

Like the derive(Component) proposal, this prevents the ability to use foreign types as events without putting them in a wrapper. Thats one of the bigger downsides imo. Ex: if winit ever sorts out its lifetime weirdness, we want to export raw winit events. This would also affect the ability to integrate things like "external physics library events".

This also feels a bit "inside out". When storing thing X in a hashset or vec, we don't define:

#[derive(Storage)]
#[storage(Vec)]
struct X {
}

You just choose to insert X into a specific storage. We should at least discuss alternatives like:

struct Events<T, S: Storage<S> = Vec<S>> {
}

app.add_event::<KeyCode>()
app.add_event_with_storage::<MyEvent, HashSet<MyEvent>>()

The downside of course is that systems would then need to include the storage type like Res<Events<MyEvent, HashSet<MyEvent>>>.

But we could alias that to something like HashSetEvents<MyEvent>.

@alice-i-cecile alice-i-cecile mentioned this pull request May 5, 2021
3 tasks
@TheRawMeatball
Copy link
Member Author

This is also an alternative, but it isn't one that's particularly appealing IMO, as this means all code must know about the underlying storage type of events, even though for most code these are irrelevant impl details. For integrating with third party types, I don't see an issue with continuing to use custom wrapper types - this is already possible and what we're doing, and it's a decent solution.

@@ -12,6 +12,8 @@ fn main() {
.run();
}

#[derive(Event)]
#[store(3)]
Copy link
Member

Choose a reason for hiding this comment

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

I don't think store(3) is descriptive enough of what is happening here. We "store" all events, not just 3 of them. I think #[smallvec(3)] makes more sense. This has the added benefit of setting the pattern for future storage derives (ex: #[vecdeque].

Copy link
Member

Choose a reason for hiding this comment

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

Although im a little worried that we aren't properly scoping this attribute to events. Theres a world where another derive uses attribute names like store or smallvec.

Copy link
Member

Choose a reason for hiding this comment

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

I love #[smallvec(3)] here for both of those reasons.

Copy link
Member

@mockersf mockersf May 7, 2021

Choose a reason for hiding this comment

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

#[smallvec(3)] is very hard to read without something linking the attribute to its derive

#[event(storage = smallvec(3))]?

@alice-i-cecile
Copy link
Member

as this means all code must know about the underlying storage type of events, even though for most code these are irrelevant impl details

I agree, and think it's really important that users can effortlessly change the storage types. Much like component storage types, this is going to be a common tuning lever. If we can tweak it in a single place and it just works (or even better, automatically explore this vs. benchmarks!) that's an incredible win for usability.

@cart
Copy link
Member

cart commented May 7, 2021

This is also an alternative, but it isn't one that's particularly appealing IMO, as this means all code must know about the underlying storage type of events, even though for most code these are irrelevant impl details

Yeah this aspect doesn't bother me as much. Especially in the context of bevy_ecs, whose primary purpose is "inversion of control".

For integrating with third party types, I don't see an issue with continuing to use custom wrapper types - this is already possible and what we're doing, and it's a decent solution.

We currently "mirror" types, which increases maintenance burden and implementation size. It also kills interop with things that use the original type. This was intentional for things like bevy_window because we want it to be a backend-agnostic abstraction, but that won't be true for all event types. Crates providing bevy "middleware" for libraries like physics and sound might be forced to create "wrapper types", which requires the dreaded event.0.field or abusing Deref traits.

@cart cart added the S-Pre-Relicense This PR was made before Bevy added the Apache license. Cannot be merged or used for other work label Jul 23, 2021
@mockersf mockersf removed the S-Pre-Relicense This PR was made before Bevy added the Apache license. Cannot be merged or used for other work label Jul 24, 2021
@alice-i-cecile
Copy link
Member

I wanted to make a collection of arbitrary events today: the Event trait would have been nice to have.

@alice-i-cecile alice-i-cecile added the X-Controversial There is active debate or serious implications around merging this PR label Apr 25, 2022
@alice-i-cecile alice-i-cecile added the S-Needs-Benchmarking This set of changes needs performance benchmarking to double-check that they help label May 18, 2022
@james7132
Copy link
Member

Closing in favor of #7957.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Feature A new feature, making something new possible S-Needs-Benchmarking This set of changes needs performance benchmarking to double-check that they help 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.

6 participants