211 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
// 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<T>,
 | 
						|
}
 | 
						|
 | 
						|
impl<'a, T: Component> Ref<'a, T> {
 | 
						|
    #[allow(missing_docs)]
 | 
						|
    pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result<Self, MissingComponent> {
 | 
						|
        let target = NonNull::new_unchecked(
 | 
						|
            archetype
 | 
						|
                .get::<T>()
 | 
						|
                .ok_or_else(MissingComponent::new::<T>)?
 | 
						|
                .as_ptr()
 | 
						|
                .add(index as usize),
 | 
						|
        );
 | 
						|
        archetype.borrow::<T>();
 | 
						|
        Ok(Self { archetype, target })
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
unsafe impl<T: Component> Send for Ref<'_, T> {}
 | 
						|
unsafe impl<T: Component> Sync for Ref<'_, T> {}
 | 
						|
 | 
						|
impl<'a, T: Component> Drop for Ref<'a, T> {
 | 
						|
    fn drop(&mut self) {
 | 
						|
        self.archetype.release::<T>();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
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<T>,
 | 
						|
    modified: &'a mut bool,
 | 
						|
}
 | 
						|
 | 
						|
impl<'a, T: Component> RefMut<'a, T> {
 | 
						|
    #[allow(missing_docs)]
 | 
						|
    pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result<Self, MissingComponent> {
 | 
						|
        let target = NonNull::new_unchecked(
 | 
						|
            archetype
 | 
						|
                .get::<T>()
 | 
						|
                .ok_or_else(MissingComponent::new::<T>)?
 | 
						|
                .as_ptr()
 | 
						|
                .add(index as usize),
 | 
						|
        );
 | 
						|
        archetype.borrow_mut::<T>();
 | 
						|
        let modified = archetype
 | 
						|
            .get_modified::<T>()
 | 
						|
            .unwrap()
 | 
						|
            .as_ptr()
 | 
						|
            .add(index as usize);
 | 
						|
        Ok(Self {
 | 
						|
            archetype,
 | 
						|
            target,
 | 
						|
            modified: &mut *modified,
 | 
						|
        })
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
unsafe impl<T: Component> Send for RefMut<'_, T> {}
 | 
						|
unsafe impl<T: Component> Sync for RefMut<'_, T> {}
 | 
						|
 | 
						|
impl<'a, T: Component> Drop for RefMut<'a, T> {
 | 
						|
    fn drop(&mut self) {
 | 
						|
        self.archetype.release_mut::<T>();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
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<T: Component>(&self) -> Option<Ref<'a, T>> {
 | 
						|
        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<T: Component>(&self) -> Option<RefMut<'a, T>> {
 | 
						|
        Some(unsafe { RefMut::new(self.archetype?, self.index).ok()? })
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
unsafe impl<'a> Send for EntityRef<'a> {}
 | 
						|
unsafe impl<'a> Sync for EntityRef<'a> {}
 |