Path: blob/main/crates/bevy_platform/src/cell/sync_unsafe_cell.rs
6849 views
#![expect(unsafe_code, reason = "SyncUnsafeCell requires unsafe code.")]12//! A reimplementation of the currently unstable [`std::cell::SyncUnsafeCell`]3//!4//! [`std::cell::SyncUnsafeCell`]: https://doc.rust-lang.org/nightly/std/cell/struct.SyncUnsafeCell.html56pub use core::cell::UnsafeCell;7use core::ptr;89/// [`UnsafeCell`], but [`Sync`].10///11/// See [tracking issue](https://github.com/rust-lang/rust/issues/95439) for upcoming native impl,12/// which should replace this one entirely (except `from_mut`).13///14/// This is just an `UnsafeCell`, except it implements `Sync`15/// if `T` implements `Sync`.16///17/// `UnsafeCell` doesn't implement `Sync`, to prevent accidental misuse.18/// You can use `SyncUnsafeCell` instead of `UnsafeCell` to allow it to be19/// shared between threads, if that's intentional.20/// Providing proper synchronization is still the task of the user,21/// making this type just as unsafe to use.22///23/// See [`UnsafeCell`] for details.24#[repr(transparent)]25pub struct SyncUnsafeCell<T: ?Sized> {26value: UnsafeCell<T>,27}2829// SAFETY: `T` is Sync, caller is responsible for upholding rust safety rules30unsafe impl<T: ?Sized + Sync> Sync for SyncUnsafeCell<T> {}3132impl<T> SyncUnsafeCell<T> {33/// Constructs a new instance of `SyncUnsafeCell` which will wrap the specified value.34#[inline]35pub const fn new(value: T) -> Self {36Self {37value: UnsafeCell::new(value),38}39}4041/// Unwraps the value.42#[inline]43pub fn into_inner(self) -> T {44self.value.into_inner()45}46}4748impl<T: ?Sized> SyncUnsafeCell<T> {49/// Gets a mutable pointer to the wrapped value.50///51/// This can be cast to a pointer of any kind.52/// Ensure that the access is unique (no active references, mutable or not)53/// when casting to `&mut T`, and ensure that there are no mutations54/// or mutable aliases going on when casting to `&T`55#[inline]56pub const fn get(&self) -> *mut T {57self.value.get()58}5960/// Returns a mutable reference to the underlying data.61///62/// This call borrows the `SyncUnsafeCell` mutably (at compile-time) which63/// guarantees that we possess the only reference.64#[inline]65pub fn get_mut(&mut self) -> &mut T {66self.value.get_mut()67}6869/// Gets a mutable pointer to the wrapped value.70///71/// See [`UnsafeCell::get`] for details.72#[inline]73pub const fn raw_get(this: *const Self) -> *mut T {74// We can just cast the pointer from `SyncUnsafeCell<T>` to `T` because75// of #[repr(transparent)] on both SyncUnsafeCell and UnsafeCell.76// See UnsafeCell::raw_get.77(this as *const T).cast_mut()78}7980#[inline]81/// Returns a `&mut SyncUnsafeCell<T>` from a `&mut T`.82pub fn from_mut(t: &mut T) -> &mut SyncUnsafeCell<T> {83let ptr = ptr::from_mut(t) as *mut SyncUnsafeCell<T>;84// SAFETY: `ptr` must be safe to mutably dereference, since it was originally85// obtained from a mutable reference. `SyncUnsafeCell` has the same representation86// as the original type `T`, since the former is annotated with #[repr(transparent)].87unsafe { &mut *ptr }88}89}9091impl<T> SyncUnsafeCell<[T]> {92/// Returns a `&[SyncUnsafeCell<T>]` from a `&SyncUnsafeCell<[T]>`.93/// # Examples94///95/// ```96/// # use bevy_platform::cell::SyncUnsafeCell;97///98/// let slice: &mut [i32] = &mut [1, 2, 3];99/// let cell_slice: &SyncUnsafeCell<[i32]> = SyncUnsafeCell::from_mut(slice);100/// let slice_cell: &[SyncUnsafeCell<i32>] = cell_slice.as_slice_of_cells();101///102/// assert_eq!(slice_cell.len(), 3);103/// ```104pub fn as_slice_of_cells(&self) -> &[SyncUnsafeCell<T>] {105let self_ptr: *const SyncUnsafeCell<[T]> = ptr::from_ref(self);106let slice_ptr = self_ptr as *const [SyncUnsafeCell<T>];107// SAFETY: `UnsafeCell<T>` and `SyncUnsafeCell<T>` have #[repr(transparent)]108// therefore:109// - `SyncUnsafeCell<T>` has the same layout as `T`110// - `SyncUnsafeCell<[T]>` has the same layout as `[T]`111// - `SyncUnsafeCell<[T]>` has the same layout as `[SyncUnsafeCell<T>]`112unsafe { &*slice_ptr }113}114}115116impl<T: Default> Default for SyncUnsafeCell<T> {117/// Creates a new `SyncUnsafeCell` with the `Default` value for T.118fn default() -> SyncUnsafeCell<T> {119SyncUnsafeCell::new(Default::default())120}121}122123impl<T> From<T> for SyncUnsafeCell<T> {124/// Creates a new `SyncUnsafeCell<T>` containing the given value.125fn from(t: T) -> SyncUnsafeCell<T> {126SyncUnsafeCell::new(t)127}128}129130131