bevy/crates/bevy_utils/src/syncunsafecell.rs
Cameron 684f07595f Add bevy_ecs::schedule_v3 module (#6587)
# Objective

Complete the first part of the migration detailed in bevyengine/rfcs#45.

## Solution

Add all the new stuff.

### TODO

- [x] Impl tuple methods.
- [x] Impl chaining.
- [x] Port ambiguity detection.
- [x] Write docs.
- [x] ~~Write more tests.~~(will do later)
- [ ] Write changelog and examples here?
- [x] ~~Replace `petgraph`.~~ (will do later)



Co-authored-by: james7132 <contact@jamessliu.com>
Co-authored-by: Michael Hsu <mike.hsu@gmail.com>
Co-authored-by: Mike Hsu <mike.hsu@gmail.com>
2023-01-17 01:39:17 +00:00

123 lines
4.2 KiB
Rust

//! A reimplementation of the currently unstable [`std::cell::SyncUnsafeCell`]
//!
//! [`std::cell::SyncUnsafeCell`]: https://doc.rust-lang.org/nightly/std/cell/struct.SyncUnsafeCell.html
pub use core::cell::UnsafeCell;
/// [`UnsafeCell`], but [`Sync`].
///
/// See [tracking issue](https://github.com/rust-lang/rust/issues/95439) for upcoming native impl,
/// which should replace this one entirely (except `from_mut`).
///
/// This is just an `UnsafeCell`, except it implements `Sync`
/// if `T` implements `Sync`.
///
/// `UnsafeCell` doesn't implement `Sync`, to prevent accidental mis-use.
/// You can use `SyncUnsafeCell` instead of `UnsafeCell` to allow it to be
/// shared between threads, if that's intentional.
/// Providing proper synchronization is still the task of the user,
/// making this type just as unsafe to use.
///
/// See [`UnsafeCell`] for details.
#[repr(transparent)]
pub struct SyncUnsafeCell<T: ?Sized> {
value: UnsafeCell<T>,
}
// SAFETY: `T` is Sync, caller is responsible for upholding rust safety rules
unsafe impl<T: ?Sized + Sync> Sync for SyncUnsafeCell<T> {}
impl<T> SyncUnsafeCell<T> {
/// Constructs a new instance of `SyncUnsafeCell` which will wrap the specified value.
#[inline]
pub const fn new(value: T) -> Self {
Self {
value: UnsafeCell::new(value),
}
}
/// Unwraps the value.
#[inline]
pub fn into_inner(self) -> T {
self.value.into_inner()
}
}
impl<T: ?Sized> SyncUnsafeCell<T> {
/// Gets a mutable pointer to the wrapped value.
///
/// This can be cast to a pointer of any kind.
/// Ensure that the access is unique (no active references, mutable or not)
/// when casting to `&mut T`, and ensure that there are no mutations
/// or mutable aliases going on when casting to `&T`
#[inline]
pub const fn get(&self) -> *mut T {
self.value.get()
}
/// Returns a mutable reference to the underlying data.
///
/// This call borrows the `SyncUnsafeCell` mutably (at compile-time) which
/// guarantees that we possess the only reference.
#[inline]
pub fn get_mut(&mut self) -> &mut T {
self.value.get_mut()
}
/// Gets a mutable pointer to the wrapped value.
///
/// See [`UnsafeCell::get`] for details.
#[inline]
pub const fn raw_get(this: *const Self) -> *mut T {
// We can just cast the pointer from `SyncUnsafeCell<T>` to `T` because
// of #[repr(transparent)] on both SyncUnsafeCell and UnsafeCell.
// See UnsafeCell::raw_get.
this as *const T as *mut T
}
#[inline]
/// Returns a `&SyncUnsafeCell<T>` from a `&mut T`.
pub fn from_mut(t: &mut T) -> &SyncUnsafeCell<T> {
// SAFETY: `&mut` ensures unique access, and `UnsafeCell<T>` and `SyncUnsafeCell<T>`
// have #[repr(transparent)]
unsafe { &*(t as *mut T as *const SyncUnsafeCell<T>) }
}
}
impl<T> SyncUnsafeCell<[T]> {
/// Returns a `&[SyncUnsafeCell<T>]` from a `&SyncUnsafeCell<[T]>`.
/// # Examples
///
/// ```
/// # use bevy_utils::syncunsafecell::SyncUnsafeCell;
///
/// let slice: &mut [i32] = &mut [1, 2, 3];
/// let cell_slice: &SyncUnsafeCell<[i32]> = SyncUnsafeCell::from_mut(slice);
/// let slice_cell: &[SyncUnsafeCell<i32>] = cell_slice.as_slice_of_cells();
///
/// assert_eq!(slice_cell.len(), 3);
/// ```
pub fn as_slice_of_cells(&self) -> &[SyncUnsafeCell<T>] {
// SAFETY: `UnsafeCell<T>` and `SyncUnsafeCell<T>` have #[repr(transparent)]
// therefore:
// - `SyncUnsafeCell<T>` has the same layout as `T`
// - `SyncUnsafeCell<[T]>` has the same layout as `[T]`
// - `SyncUnsafeCell<[T]>` has the same layout as `[SyncUnsafeCell<T>]`
unsafe { &*(self as *const SyncUnsafeCell<[T]> as *const [SyncUnsafeCell<T>]) }
}
}
impl<T: Default> Default for SyncUnsafeCell<T> {
/// Creates an `SyncUnsafeCell`, with the `Default` value for T.
fn default() -> SyncUnsafeCell<T> {
SyncUnsafeCell::new(Default::default())
}
}
impl<T> From<T> for SyncUnsafeCell<T> {
/// Creates a new `SyncUnsafeCell<T>` containing the given value.
fn from(t: T) -> SyncUnsafeCell<T> {
SyncUnsafeCell::new(t)
}
}