bevy/crates/bevy_ecs/hecs/src/borrow.rs
2020-07-22 12:42:12 -07:00

210 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_mutated::<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> {}