forked from bevyengine/bevy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Objective Currently, `Local` has a `Sync` bound. Theoretically this is unnecessary as a local can only ever be accessed from its own system, ensuring exclusive access on one thread. This PR removes this restriction. ## Solution - By removing the `Resource` bound from `Local` and adding the new `SyncCell` threading primative, `Local` can have the `Sync` bound removed. ## Changelog ### Added - Added `SyncCell` to `bevy_utils` ### Changed - Removed `Resource` bound from `Local` - `Local` is now wrapped in a `SyncCell` ## Migration Guide - Any code relying on `Local<T>` having `T: Resource` may have to be changed, but this is unlikely. Co-authored-by: PROMETHIA-27 <42193387+PROMETHIA-27@users.noreply.github.com>
- Loading branch information
Showing
3 changed files
with
49 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/// See [`Exclusive`](https://github.com/rust-lang/rust/issues/98407) for stdlib's upcoming implementation, | ||
/// which should replace this one entirely. | ||
/// | ||
/// Provides a wrapper that allows making any type unconditionally [`Sync`] by only providing mutable access. | ||
#[repr(transparent)] | ||
pub struct SyncCell<T: ?Sized> { | ||
inner: T, | ||
} | ||
|
||
impl<T: Sized> SyncCell<T> { | ||
/// Construct a new instance of a `SyncCell` from the given value. | ||
pub fn new(inner: T) -> Self { | ||
Self { inner } | ||
} | ||
|
||
/// Deconstruct this `SyncCell` into its inner value. | ||
pub fn to_inner(Self { inner }: Self) -> T { | ||
inner | ||
} | ||
} | ||
|
||
impl<T: ?Sized> SyncCell<T> { | ||
/// Get a reference to this `SyncCell`'s inner value. | ||
pub fn get(&mut self) -> &mut T { | ||
&mut self.inner | ||
} | ||
|
||
/// Build a mutable reference to a `SyncCell` from a mutable reference | ||
/// to its inner value, to skip constructing with [`new()`](SyncCell::new()). | ||
pub fn from_mut(r: &'_ mut T) -> &'_ mut SyncCell<T> { | ||
// SAFETY: repr is transparent, so refs have the same layout; and `SyncCell` properties are `&mut`-agnostic | ||
unsafe { &mut *(r as *mut T as *mut SyncCell<T>) } | ||
} | ||
} | ||
|
||
// SAFETY: `Sync` only allows multithreaded access via immutable reference. | ||
// As `SyncCell` requires an exclusive reference to access the wrapped value, | ||
// marking this type as `Sync` does not actually allow threaded access to the inner value. | ||
unsafe impl<T: ?Sized> Sync for SyncCell<T> {} |