// Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // modified by Bevy contributors use core::{ ops::{Deref, DerefMut}, ptr::NonNull, sync::atomic::{AtomicUsize, Ordering}, fmt::Debug, }; use crate::{archetype::Archetype, Component, MissingComponent}; pub struct AtomicBorrow(AtomicUsize); impl AtomicBorrow { pub const fn new() -> Self { Self(AtomicUsize::new(0)) } pub fn borrow(&self) -> bool { let value = self.0.fetch_add(1, Ordering::Acquire).wrapping_add(1); if value == 0 { // Wrapped, this borrow is invalid! core::panic!() } if value & UNIQUE_BIT != 0 { self.0.fetch_sub(1, Ordering::Release); false } else { true } } pub fn borrow_mut(&self) -> bool { self.0 .compare_exchange(0, UNIQUE_BIT, Ordering::Acquire, Ordering::Relaxed) .is_ok() } pub fn release(&self) { let value = self.0.fetch_sub(1, Ordering::Release); debug_assert!(value != 0, "unbalanced release"); debug_assert!(value & UNIQUE_BIT == 0, "shared release of unique borrow"); } pub fn release_mut(&self) { let value = self.0.fetch_and(!UNIQUE_BIT, Ordering::Release); debug_assert_ne!(value & UNIQUE_BIT, 0, "unique release of shared borrow"); } } const UNIQUE_BIT: usize = !(usize::max_value() >> 1); /// Shared borrow of an entity's component #[derive(Clone)] pub struct Ref<'a, T: Component> { archetype: &'a Archetype, target: NonNull, } impl<'a, T: Component> Ref<'a, T> { #[allow(missing_docs)] pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result { let target = NonNull::new_unchecked( archetype .get::() .ok_or_else(MissingComponent::new::)? .as_ptr() .add(index as usize), ); archetype.borrow::(); Ok(Self { archetype, target }) } } unsafe impl Send for Ref<'_, T> {} unsafe impl Sync for Ref<'_, T> {} impl<'a, T: Component> Drop for Ref<'a, T> { fn drop(&mut self) { self.archetype.release::(); } } impl<'a, T: Component> Deref for Ref<'a, T> { type Target = T; fn deref(&self) -> &T { unsafe { self.target.as_ref() } } } impl<'a, T: Component> Debug for Ref<'a,T> where T: Debug { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.deref().fmt(f) } } /// Unique borrow of an entity's component pub struct RefMut<'a, T: Component> { archetype: &'a Archetype, target: NonNull, modified: &'a mut bool, } impl<'a, T: Component> RefMut<'a, T> { #[allow(missing_docs)] pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result { let target = NonNull::new_unchecked( archetype .get::() .ok_or_else(MissingComponent::new::)? .as_ptr() .add(index as usize), ); archetype.borrow_mut::(); let modified = archetype .get_mutated::() .unwrap() .as_ptr() .add(index as usize); Ok(Self { archetype, target, modified: &mut *modified, }) } } unsafe impl Send for RefMut<'_, T> {} unsafe impl Sync for RefMut<'_, T> {} impl<'a, T: Component> Drop for RefMut<'a, T> { fn drop(&mut self) { self.archetype.release_mut::(); } } impl<'a, T: Component> Deref for RefMut<'a, T> { type Target = T; fn deref(&self) -> &T { unsafe { self.target.as_ref() } } } impl<'a, T: Component> DerefMut for RefMut<'a, T> { fn deref_mut(&mut self) -> &mut T { *self.modified = true; unsafe { self.target.as_mut() } } } impl<'a, T: Component> Debug for RefMut<'a,T> where T: Debug { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { self.deref().fmt(f) } } /// Handle to an entity with any component types #[derive(Copy, Clone)] pub struct EntityRef<'a> { archetype: Option<&'a Archetype>, index: u32, } impl<'a> EntityRef<'a> { /// Construct a `Ref` for an entity with no components pub(crate) fn empty() -> Self { Self { archetype: None, index: 0, } } pub(crate) unsafe fn new(archetype: &'a Archetype, index: u32) -> Self { Self { archetype: Some(archetype), index, } } /// Borrow the component of type `T`, if it exists /// /// Panics if the component is already uniquely borrowed from another entity with the same /// components. pub fn get(&self) -> Option> { Some(unsafe { Ref::new(self.archetype?, self.index).ok()? }) } /// Uniquely borrow the component of type `T`, if it exists /// /// Panics if the component is already borrowed from another entity with the same components. pub fn get_mut(&self) -> Option> { Some(unsafe { RefMut::new(self.archetype?, self.index).ok()? }) } } unsafe impl<'a> Send for EntityRef<'a> {} unsafe impl<'a> Sync for EntityRef<'a> {}