-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
Arc-d assets #15813
base: main
Are you sure you want to change the base?
Arc-d assets #15813
Conversation
Can you fix the inconsistency between "[ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the concept of storing assets in an Arc
. I find that I very rarely mutate existing assets, only add/remove/swap, so Arc
s for assets make perfect sense to me. I am somewhat worried about a lot of usages of get_cloned_mut
that this causes in the rest of the codebase though.
examples/asset/arc_asset.rs
Outdated
@@ -0,0 +1,251 @@ | |||
//! This example illustrates how to use assets in an async context (through locking). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//! This example illustrates how to use assets in an async context (through locking). | |
//! This example illustrates how to use assets in an async context (through cloning the underlying `Arc`, effectively locking the asset from mutation). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dropped the whole "locking" wording, that was actually just an artifact from my "asset locking" PR (which I stole this example from, lol). Done!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still do like the naming of "locking" an asset, since that is effectively what you're doing when you've got 2+ ref counts to an asset - you're locking it for mutation. Maybe this term could be used in docs somewhere?
/// When an asset has a reference count of more than 1, this asset is considered *locked* for mutation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I intentionally want to avoid calling it "locked" because you can still replace the asset entirely. So the asset isn't locked, only the particular "instance" of that asset? The terminology gets a little unclear. I also think the comment on get_arc
makes it more clear what the tradeoffs are:
/// Be careful with holding the Arc indefinitely: holding the
/// [`Arc`] (or a [`Weak`]) prevents the asset from being mutated in place. This can incur
/// clones when using `get_cloned_mut`, or can just entirely block mutation when using
/// `get_in_place_mut`.
Removing these functions makes it simpler to redesign them for when assets are Arc'd.
Many callers expect to be able to call `meshes.add(Rectangle::new(50.0, 100.0))`. Now we can keep all these callsites the same (while still supporting inserting/adding `Arc`s directly).
Now for assets that impl `Clone`, we can get a mutable borrow to the asset always by cloning.
Now we can mutate assets in place as long as there are no more Arcs or Weaks for that asset.
This is basically the same as `get_cloned_mut` but using reflection. This is not really intended to be used publicly, but the reflect.rs needs a clone that only relies on reflection, so making it public seems fine.
…he `get_*_mut` variants.
…e assets as Arcs.
…rceAsset>` in `RenderAsset`.
…ing with `Arc`s.
…periods of time.
Done! |
Objective
Fixes #15723. This is an alternative to #15346 (and the associated PR #15359) obsolete. Note if we decide asset locking is preferable, there are learnings from this PR we can apply to #15359.
Solution
Assets are now stored as
Arc<A>
instead of justA
.get
remains the same, but I've added an alternative calledget_arc
which returns a clone of the Arc that stores an asset.Replaced the
get_mut
with one ofget_cloned_mut
,get_inplace_mut
, andget_reflect_cloned_mut
(this last one is just because it's necessary for reflection, but not necessarily needed for users).Added
add_arc
andinsert_arc
to allow addingArc
types directly.add
currently takesInto<A>
. Trying to change this toInto<Arc<A>>
breaks a lot of callsites likemeshes.add(Rectangle::new(1.0, 2.0))
(since this requires twoInto
calls, which Rust can't figure out).add_arc
takeInto<Arc<A>>
is a fine middle ground to allow bothArc
-ed assets and owned assets.insert_arc
.RenderAsset
now takes anArc<Self::SourceAsset>
. This means in most cases, cloning the asset can be skipped when passing data to the render world. Data only needs to be cloned if you mutate an asset.Testing
Showcase
Migration Guide
Assets::get_mut
has been removed. Useget_cloned_mut
forClone
assets, orget_in_place_mut
for non-Clone
assets (and handle the case where the asset is aliased).Assets::iter_mut
now returns an iterator of&mut Arc<A>
. Consider usingArc::make_mut
forClone
assets, orArc::get_mut
for non-Clone
assets (and handle the case where the asset is aliased).RenderAsset
s now take anArc<Self::SourceAsset>
. Consider usingArc::try_unwrap()
and falling back to a clone if the asset is aliased (try_unwrap
returns an error). Otherwise, prefer borrowing the source asset's data instead of moving it.