Add thread safety to "function systems"

This commit is contained in:
Carter Anderson 2020-04-28 01:27:18 -07:00
parent d5dcc96c39
commit d5a33c9d0d
4 changed files with 45 additions and 5 deletions

View file

@ -107,6 +107,9 @@ pub trait ResourceSet: Send + Sync {
{
unsafe { Self::fetch_unchecked(resources) }
}
fn read_types() -> Vec<ResourceTypeId>;
fn write_types() -> Vec<ResourceTypeId>;
}
/// Blanket trait for resource types.
@ -365,6 +368,8 @@ impl ResourceSet for () {
type PreparedResources = ();
unsafe fn fetch_unchecked(_: &Resources) {}
fn read_types() -> Vec<ResourceTypeId> { Vec::new() }
fn write_types() -> Vec<ResourceTypeId> { Vec::new() }
}
impl<T: Resource> ResourceSet for Read<T> {
@ -376,6 +381,10 @@ impl<T: Resource> ResourceSet for Read<T> {
.unwrap_or_else(|| panic!("Failed to fetch resource!: {}", std::any::type_name::<T>()));
PreparedRead::new(resource.deref() as *const T)
}
fn read_types() -> Vec<ResourceTypeId> {
vec![ResourceTypeId::of::<T>()]
}
fn write_types() -> Vec<ResourceTypeId> { Vec::new() }
}
impl<T: Resource> ResourceSet for Write<T> {
type PreparedResources = PreparedWrite<T>;
@ -386,6 +395,12 @@ impl<T: Resource> ResourceSet for Write<T> {
.unwrap_or_else(|| panic!("Failed to fetch resource!: {}", std::any::type_name::<T>()));
PreparedWrite::new(resource.deref_mut() as *mut T)
}
fn read_types() -> Vec<ResourceTypeId> {
Vec::new()
}
fn write_types() -> Vec<ResourceTypeId> {
vec![ResourceTypeId::of::<T>()]
}
}
macro_rules! impl_resource_tuple {
@ -398,6 +413,16 @@ macro_rules! impl_resource_tuple {
unsafe fn fetch_unchecked(resources: &Resources) -> Self::PreparedResources {
($( $ty::fetch_unchecked(resources), )*)
}
fn read_types() -> Vec<ResourceTypeId> {
let mut vec = vec![];
$( vec.extend($ty::read_types()); )*
vec
}
fn write_types() -> Vec<ResourceTypeId> {
let mut vec = vec![];
$( vec.extend($ty::write_types()); )*
vec
}
}
};
}

View file

@ -32,8 +32,8 @@ use legion_core::{
#[derive(Derivative, Debug, Clone)]
#[derivative(Default(bound = ""))]
pub struct Access<T> {
reads: Vec<T>,
writes: Vec<T>,
pub reads: Vec<T>,
pub writes: Vec<T>,
}
/// Structure describing the resource and component access conditions of the system.

View file

@ -22,8 +22,13 @@ where
R: EntityFilter + Sync + 'static,
X: ResourceSet<PreparedResources = X> + 'static,
{
let resource_access: Access<ResourceTypeId> = Access::default();
let component_access: Access<ComponentTypeId> = Access::default();
let mut resource_access: Access<ResourceTypeId> = Access::default();
resource_access.reads.extend(X::read_types().iter());
resource_access.writes.extend(X::write_types().iter());
let mut component_access: Access<ComponentTypeId> = Access::default();
component_access.reads.extend(Q::read_types().iter());
component_access.writes.extend(Q::write_types().iter());
let run_fn = SystemFnWrapper(
move |_,

View file

@ -1,4 +1,4 @@
use crate::resource::{PreparedRead, ResourceSet, Resources, Resource, PreparedWrite};
use crate::resource::{PreparedRead, ResourceSet, Resources, Resource, PreparedWrite, ResourceTypeId};
use std::ops::{Deref, DerefMut};
impl<T: Resource> ResourceSet for PreparedRead<T> {
@ -10,6 +10,10 @@ impl<T: Resource> ResourceSet for PreparedRead<T> {
.unwrap_or_else(|| panic!("Failed to fetch resource!: {}", std::any::type_name::<T>()));
PreparedRead::new(resource.deref() as *const T)
}
fn read_types() -> Vec<ResourceTypeId> {
vec![ResourceTypeId::of::<T>()]
}
fn write_types() -> Vec<ResourceTypeId> { Vec::new() }
}
impl<T: Resource> ResourceSet for PreparedWrite<T> {
@ -21,4 +25,10 @@ impl<T: Resource> ResourceSet for PreparedWrite<T> {
.unwrap_or_else(|| panic!("Failed to fetch resource!: {}", std::any::type_name::<T>()));
PreparedWrite::new(resource.deref_mut() as *mut T)
}
fn read_types() -> Vec<ResourceTypeId> {
Vec::new()
}
fn write_types() -> Vec<ResourceTypeId> {
vec![ResourceTypeId::of::<T>()]
}
}