Skip to content

Commit

Permalink
Ptrify everything
Browse files Browse the repository at this point in the history
  • Loading branch information
TheRawMeatball committed Oct 23, 2021
1 parent feea9e0 commit 40b1366
Show file tree
Hide file tree
Showing 19 changed files with 949 additions and 620 deletions.
22 changes: 11 additions & 11 deletions crates/bevy_ecs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,17 +126,17 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
self.#field.get_components(&mut func);
});
field_from_components.push(quote! {
#field: <#field_type as #ecs_path::bundle::Bundle>::from_components(&mut func),
#field: <#field_type as #ecs_path::bundle::Bundle>::from_components(ctx, &mut func),
});
} else {
field_component_ids.push(quote! {
component_ids.push(components.init_component::<#field_type>(storages));
});
field_get_components.push(quote! {
#ecs_path::ptr::OwningPtr::make(self.#field, func);
#ecs_path::ptr::OwningPtr::make(self.#field, &mut func);
});
field_from_components.push(quote! {
#field: func().inner().cast::<#field_type>().read(),
#field: func(ctx).inner().cast::<#field_type>().read(),
});
}
}
Expand All @@ -158,9 +158,9 @@ pub fn derive_bundle(input: TokenStream) -> TokenStream {
}

#[allow(unused_variables, unused_mut, non_snake_case)]
unsafe fn from_components<'a, F>(func: F) -> Self
unsafe fn from_components<T, F>(ctx: &mut T, mut func: F) -> Self
where
F: FnMut() -> #ecs_path::ptr::OwningPtr<'a> + 'a
F: FnMut(&mut T) -> #ecs_path::ptr::OwningPtr<'_>
{
Self {
#(#field_from_components)*
Expand Down Expand Up @@ -211,20 +211,20 @@ pub fn impl_query_set(_input: TokenStream) -> TokenStream {
let query_fn_mut = &query_fn_muts[0..query_count];
tokens.extend(TokenStream::from(quote! {
impl<'w, 's, #(#query: WorldQuery + 'static,)* #(#filter: WorldQuery + 'static,)*> SystemParam for QuerySet<'w, 's, (#(QueryState<#query, #filter>,)*)>
where #(#filter::Fetch: FilterFetch,)*
where #(for<'x, 'y> QueryFetch<'x, 'y, #filter>: FilterFetch<'x, 'y>,)*
{
type Fetch = QuerySetState<(#(QueryState<#query, #filter>,)*)>;
}

// SAFE: All Queries are constrained to ReadOnlyFetch, so World is only read
// SAFE: All Queries are constrained to ReadOnlyQuery, so World is only read
unsafe impl<#(#query: WorldQuery + 'static,)* #(#filter: WorldQuery + 'static,)*> ReadOnlySystemParamFetch for QuerySetState<(#(QueryState<#query, #filter>,)*)>
where #(#query::Fetch: ReadOnlyFetch,)* #(#filter::Fetch: FilterFetch,)*
where #(#query: ReadOnlyQuery,)* #(for<'x, 'y> QueryFetch<'x, 'y, #filter>: FilterFetch<'x, 'y>,)*
{ }

// SAFE: Relevant query ComponentId and ArchetypeComponentId access is applied to SystemMeta. If any QueryState conflicts
// with any prior access, a panic will occur.
unsafe impl<#(#query: WorldQuery + 'static,)* #(#filter: WorldQuery + 'static,)*> SystemParamState for QuerySetState<(#(QueryState<#query, #filter>,)*)>
where #(#filter::Fetch: FilterFetch,)*
where #(for<'x, 'y> QueryFetch<'x, 'y, #filter>: FilterFetch<'x, 'y>,)*
{
type Config = ();
fn init(world: &mut World, system_meta: &mut SystemMeta, config: Self::Config) -> Self {
Expand Down Expand Up @@ -264,7 +264,7 @@ pub fn impl_query_set(_input: TokenStream) -> TokenStream {
}

impl<'w, 's, #(#query: WorldQuery + 'static,)* #(#filter: WorldQuery + 'static,)*> SystemParamFetch<'w, 's> for QuerySetState<(#(QueryState<#query, #filter>,)*)>
where #(#filter::Fetch: FilterFetch,)*
where #(for<'x, 'y> QueryFetch<'x, 'y, #filter>: FilterFetch<'x, 'y>,)*
{
type Item = QuerySet<'w, 's, (#(QueryState<#query, #filter>,)*)>;

Expand All @@ -285,7 +285,7 @@ pub fn impl_query_set(_input: TokenStream) -> TokenStream {
}

impl<'w, 's, #(#query: WorldQuery,)* #(#filter: WorldQuery,)*> QuerySet<'w, 's, (#(QueryState<#query, #filter>,)*)>
where #(#filter::Fetch: FilterFetch,)*
where #(for<'x, 'y> QueryFetch<'x, 'y, #filter>: FilterFetch<'x, 'y>,)*
{
#(#query_fn_mut)*
}
Expand Down
12 changes: 6 additions & 6 deletions crates/bevy_ecs/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ pub unsafe trait Bundle: Send + Sync + 'static {
/// # Safety
/// Caller must return data for each component in the bundle, in the order of this bundle's
/// Components
unsafe fn from_components<'a, F>(func: F) -> Self
unsafe fn from_components<T, F>(ctx: &mut T, func: F) -> Self
where
F: FnMut() -> OwningPtr<'a> + 'a,
F: FnMut(&mut T) -> OwningPtr<'_>,
Self: Sized;

/// Calls `func` on each value, in the order of this bundle's Components. This will
Expand All @@ -108,13 +108,13 @@ macro_rules! tuple_impl {

#[allow(unused_variables, unused_mut)]
#[allow(clippy::unused_unit)]
unsafe fn from_components<'a, F>(func: F) -> Self
unsafe fn from_components<T, F>(ctx: &mut T, mut func: F) -> Self
where
F: FnMut() -> OwningPtr<'a> + 'a
F: FnMut(&mut T) -> OwningPtr<'_>
{
#[allow(non_snake_case)]
let ($(mut $name,)*) = (
$(func().inner().cast::<$name>(),)*
$(func(ctx).inner().cast::<$name>(),)*
);
($($name.read(),)*)
}
Expand All @@ -124,7 +124,7 @@ macro_rules! tuple_impl {
#[allow(non_snake_case)]
let ($(mut $name,)*) = self;
$(
OwningPtr::make($name, func);
OwningPtr::make($name, &mut func);
)*
}
}
Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub mod prelude {
#[cfg(test)]
mod tests {
use crate as bevy_ecs;
use crate::query::QueryFetch;
use crate::{
bundle::Bundle,
component::{Component, ComponentId},
Expand Down Expand Up @@ -887,7 +888,7 @@ mod tests {

fn get_filtered<F: WorldQuery>(world: &mut World) -> Vec<Entity>
where
F::Fetch: FilterFetch,
for<'x, 'y> QueryFetch<'x, 'y, F>: FilterFetch<'x, 'y>,
{
world
.query_filtered::<Entity, F>()
Expand Down
104 changes: 85 additions & 19 deletions crates/bevy_ecs/src/ptr.rs
Original file line number Diff line number Diff line change
@@ -1,83 +1,149 @@
use std::{marker::PhantomData, mem::MaybeUninit, ptr::NonNull};

/// Type-erased pointer into memory. Guaranteed to be correctly aligned, non-null and safe to read for a particular type.
#[derive(Copy, Clone)]
pub struct Ptr<'a>(NonNull<u8>, PhantomData<&'a u8>);
#[derive(Copy, Clone)]

/// Type-erased pointer into memory. Guaranteed to be correctly aligned, non-null and safe to modify for a particular type.
pub struct PtrMut<'a>(NonNull<u8>, PhantomData<&'a mut u8>);

/// Type-erased pointer into memory. Guaranteed to be correctly aligned, non-null and safe to move out of for a particular type.
pub struct OwningPtr<'a>(NonNull<u8>, PhantomData<&'a mut u8>);

pub struct ThinSlicePtr<'a, T> {
ptr: NonNull<T>,
#[cfg(debug_assertions)]
len: usize,
_marker: PhantomData<&'a [T]>,
}

impl<T> Clone for ThinSlicePtr<'_, T> {
fn clone(&self) -> Self {
Self {
ptr: self.ptr,
#[cfg(debug_assertions)]
len: self.len,
_marker: PhantomData,
}
}
}
impl<T> Copy for ThinSlicePtr<'_, T> {}

impl<'a, T> ThinSlicePtr<'a, T> {
pub fn new(slice: &'a [T]) -> Self {
unsafe {
Self {
ptr: NonNull::new_unchecked(slice.as_ptr() as *mut _),
#[cfg(debug_assertions)]
len: slice.len(),
_marker: PhantomData,
}
}
}

/// # Safety
/// ptr must be valid for the returned lifetime.
pub unsafe fn new_raw(ptr: NonNull<T>, #[cfg(debug_assertions)] len: usize) -> Self {
Self {
ptr,
#[cfg(debug_assertions)]
len,
_marker: PhantomData,
}
}

/// # Safety
/// index must not be out of bounds
pub unsafe fn index(self, index: usize) -> &'a T {
debug_assert!(index < self.len);
&*self.ptr.as_ptr().add(index)
}

/// # Safety
/// index must not be out of bounds, and the same element must not be mutably accessed twice.
pub unsafe fn index_mut(self, index: usize) -> &'a mut T {
debug_assert!(index < self.len);
&mut *self.ptr.as_ptr().add(index)
}
}

macro_rules! impl_ptr {
($ptr:ident) => {
impl $ptr<'_> {
/// Safety: the offset cannot make the existing ptr null, or take it out of bounds for it's allocation.
/// # Safety
/// the offset cannot make the existing ptr null, or take it out of bounds for it's allocation.
pub unsafe fn offset(self, count: isize) -> Self {
Self(
NonNull::new_unchecked(self.0.as_ptr().offset(count)),
PhantomData,
)
}

/// Safety: the offset cannot make the existing ptr null, or take it out of bounds for it's allocation.
/// # Safety
/// the offset cannot make the existing ptr null, or take it out of bounds for it's allocation.
pub unsafe fn add(self, count: usize) -> Self {
Self(
NonNull::new_unchecked(self.0.as_ptr().add(count)),
PhantomData,
)
}

/// # Safety
/// the lifetime for the returned item must not exceed the lifetime `inner` is valid for
pub unsafe fn new(inner: NonNull<u8>) -> Self {
Self(inner, PhantomData)
}

pub unsafe fn inner_nonnull(self) -> NonNull<u8> {
self.0
}
}
};
}

impl_ptr!(Ptr);
impl<'a> Ptr<'a> {
pub unsafe fn inner(self) -> *const u8 {
self.0.as_ptr() as *const _
/// # Safety
/// another PtrMut for the same Ptr shouldn't be created until the first is dropped.
pub unsafe fn assert_unique(self) -> PtrMut<'a> {
PtrMut(self.0, PhantomData)
}

/// # Safety
/// Must point to a valid T
pub unsafe fn deref<T>(self) -> &'a T {
&*self.inner().cast()
&*self.0.as_ptr().cast()
}
}
impl_ptr!(PtrMut);
impl<'a> PtrMut<'a> {
pub unsafe fn inner(self) -> *mut u8 {
self.0.as_ptr()
pub fn inner(self) -> NonNull<u8> {
self.0
}

/// # Safety
/// must have right to drop or move out of PtrMut, and current PtrMut should not be accessed again unless it's written to again.
pub unsafe fn promote(self) -> OwningPtr<'a> {
OwningPtr(self.0, PhantomData)
}

/// # Safety
/// Must point to a valid T
pub unsafe fn deref_mut<T>(self) -> &'a mut T {
&mut *self.inner().cast()
&mut *self.inner().as_ptr().cast()
}
}
impl_ptr!(OwningPtr);
impl<'a> OwningPtr<'a> {
pub unsafe fn inner(self) -> *mut u8 {
pub fn inner(self) -> *mut u8 {
self.0.as_ptr()
}

pub fn make<T, F: FnOnce(OwningPtr<'_>) -> R, R>(val: T, f: F) -> R {
let temp = MaybeUninit::new(val);
let mut temp = MaybeUninit::new(val);
let ptr = unsafe { NonNull::new_unchecked(temp.as_mut_ptr().cast::<u8>()) };
f(Self(ptr, PhantomData))
}

/// # Safety
/// must point to a valid T.
pub unsafe fn read<T>(self) -> T {
self.inner().cast::<T>().read()
}

pub unsafe fn deref_mut<T>(self) -> &'a mut T {
&mut *self.inner().cast()
}
}
Loading

0 comments on commit 40b1366

Please sign in to comment.