Sfoglia il codice sorgente

Implemented async systems

master
Bergmann89 5 anni fa
parent
commit
3658c9322a
8 ha cambiato i file con 122 aggiunte e 24 eliminazioni
  1. +1
    -0
      async-ecs/Cargo.toml
  2. +5
    -4
      async-ecs/src/access/accessor.rs
  3. +9
    -5
      async-ecs/src/dispatcher/builder.rs
  4. +13
    -6
      async-ecs/src/dispatcher/dispatchable.rs
  5. +1
    -1
      async-ecs/src/lib.rs
  6. +9
    -6
      async-ecs/src/main.rs
  7. +80
    -2
      async-ecs/src/system/mod.rs
  8. +4
    -0
      async-ecs/src/system/system_data.rs

+ 1
- 0
async-ecs/Cargo.toml Vedi File

@@ -7,6 +7,7 @@ edition = "2018"
[dependencies] [dependencies]
async-ecs-derive = "0.1" async-ecs-derive = "0.1"
env_logger = "0.8" env_logger = "0.8"
futures = "0.3"
hashbrown = "0.9" hashbrown = "0.9"
hibitset = "0.6" hibitset = "0.6"
log = "0.4" log = "0.4"


+ 5
- 4
async-ecs/src/access/accessor.rs Vedi File

@@ -3,7 +3,7 @@ use std::ops::Deref;


use crate::{ use crate::{
resource::ResourceId, resource::ResourceId,
system::{DynamicSystemData, System, SystemData},
system::{DynamicSystemData, SystemData, WithSystemData},
}; };


pub trait Accessor: Sized { pub trait Accessor: Sized {
@@ -28,14 +28,15 @@ pub struct StaticAccessor<T> {
pub enum AccessorCow<'a, 'b, T> pub enum AccessorCow<'a, 'b, T>
where where
AccessorType<'a, T>: 'b, AccessorType<'a, T>: 'b,
T: System<'a> + ?Sized,
T: WithSystemData<'a> + ?Sized,
'a: 'b, 'a: 'b,
{ {
Borrow(&'b AccessorType<'a, T>), Borrow(&'b AccessorType<'a, T>),
Owned(AccessorType<'a, T>), Owned(AccessorType<'a, T>),
} }


pub type AccessorType<'a, T> = <<T as System<'a>>::SystemData as DynamicSystemData<'a>>::Accessor;
pub type AccessorType<'a, T> =
<<T as WithSystemData<'a>>::SystemData as DynamicSystemData<'a>>::Accessor;


/* StaticAccessor */ /* StaticAccessor */


@@ -63,7 +64,7 @@ where
impl<'a, 'b, T> Deref for AccessorCow<'a, 'b, T> impl<'a, 'b, T> Deref for AccessorCow<'a, 'b, T>
where where
AccessorType<'a, T>: 'b, AccessorType<'a, T>: 'b,
T: System<'a> + ?Sized + 'b,
T: WithSystemData<'a> + ?Sized + 'b,
'a: 'b, 'a: 'b,
{ {
type Target = AccessorType<'a, T>; type Target = AccessorType<'a, T>;


+ 9
- 5
async-ecs/src/dispatcher/builder.rs Vedi File

@@ -3,7 +3,7 @@ use std::fmt::Debug;


use tokio::{spawn, sync::watch::channel}; use tokio::{spawn, sync::watch::channel};


use crate::{access::Accessor, resource::ResourceId, system::System};
use crate::{access::Accessor, resource::ResourceId, system::AsyncSystem};


use super::{task::execute, BoxedDispatchable, Dispatcher, Error, Receiver, Sender, SharedWorld}; use super::{task::execute, BoxedDispatchable, Dispatcher, Error, Receiver, Sender, SharedWorld};


@@ -62,7 +62,7 @@ impl Builder {


pub fn with<S>(mut self, system: S, name: &str, dependencies: &[&str]) -> Result<Self, Error> pub fn with<S>(mut self, system: S, name: &str, dependencies: &[&str]) -> Result<Self, Error>
where where
S: for<'s> System<'s> + Send + 'static,
S: for<'s> AsyncSystem<'s> + Send + 'static,
{ {
self.add(system, name, dependencies)?; self.add(system, name, dependencies)?;


@@ -76,7 +76,7 @@ impl Builder {
dependencies: &[&str], dependencies: &[&str],
) -> Result<&mut Self, Error> ) -> Result<&mut Self, Error>
where where
S: for<'s> System<'s> + Send + 'static,
S: for<'s> AsyncSystem<'s> + Send + 'static,
{ {
let name = name.to_owned(); let name = name.to_owned();
let id = self.next_id(); let id = self.next_id();
@@ -208,7 +208,7 @@ impl Default for Builder {
impl Item { impl Item {
fn new<S>(name: String, system: S) -> Self fn new<S>(name: String, system: S) -> Self
where where
S: for<'s> System<'s> + Send + 'static,
S: for<'s> AsyncSystem<'s> + Send + 'static,
{ {
let (sender, receiver) = channel(()); let (sender, receiver) = channel(());


@@ -231,7 +231,11 @@ impl Item {
mod tests { mod tests {
use super::*; use super::*;


use crate::{access::AccessorCow, system::DynamicSystemData, world::World};
use crate::{
access::AccessorCow,
system::{DynamicSystemData, System},
world::World,
};


#[test] #[test]
fn dependencies_on_read_and_write() { fn dependencies_on_read_and_write() {


+ 13
- 6
async-ecs/src/dispatcher/dispatchable.rs Vedi File

@@ -1,21 +1,28 @@
use std::ops::Deref;
use std::pin::Pin;

use futures::future::{Future, FutureExt};

use crate::{ use crate::{
system::{DynamicSystemData, System},
system::{AsyncSystem, DynamicSystemData},
world::World, world::World,
}; };


pub type BoxedFuture<'a> = Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
pub type BoxedDispatchable = Box<dyn for<'a> Dispatchable<'a> + Send>; pub type BoxedDispatchable = Box<dyn for<'a> Dispatchable<'a> + Send>;


pub trait Dispatchable<'a> { pub trait Dispatchable<'a> {
fn run(&mut self, world: &'a World);
fn run(&mut self, world: &'a World) -> BoxedFuture<'a>;
} }


impl<'a, T> Dispatchable<'a> for T impl<'a, T> Dispatchable<'a> for T
where where
T: System<'a>,
T: AsyncSystem<'a>,
<T as AsyncSystem<'a>>::Future: Send,
{ {
fn run(&mut self, world: &'a World) {
let data = T::SystemData::fetch(&self.accessor(), world);
fn run(&mut self, world: &'a World) -> BoxedFuture<'a> {
let data = T::SystemData::fetch(self.accessor().deref(), world);


self.run(data);
self.run(data).boxed()
} }
} }

+ 1
- 1
async-ecs/src/lib.rs Vedi File

@@ -15,5 +15,5 @@ pub use access::{Join, ReadStorage, WriteStorage};
pub use dispatcher::Dispatcher; pub use dispatcher::Dispatcher;
pub use resource::Resources; pub use resource::Resources;
pub use storage::VecStorage; pub use storage::VecStorage;
pub use system::System;
pub use system::{AsyncSystem, System};
pub use world::World; pub use world::World;

+ 9
- 6
async-ecs/src/main.rs Vedi File

@@ -2,8 +2,8 @@ use std::io::Error as IoError;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};


use async_ecs::{ use async_ecs::{
dispatcher::Error as DispatcherError, Dispatcher, Join, ReadStorage, System, VecStorage, World,
WriteStorage,
dispatcher::Error as DispatcherError, AsyncSystem, Dispatcher, Join, ReadStorage, System,
VecStorage, World, WriteStorage,
}; };
use async_ecs_derive::Component; use async_ecs_derive::Component;
use log::info; use log::info;
@@ -71,8 +71,8 @@ async fn run() -> Result<(), Error> {
Ok(()) Ok(())
} }


const ENTITY_COUNT: usize = 100_000;
const REPEAT_COUNT: u32 = 100;
const ENTITY_COUNT: usize = 1_000_000;
const REPEAT_COUNT: u32 = 10;


#[derive(Debug, Component)] #[derive(Debug, Component)]
#[storage(VecStorage)] #[storage(VecStorage)]
@@ -156,15 +156,18 @@ impl<'a> System<'a> for Move {
} }
} }


impl<'a> System<'a> for Accelerate {
impl<'a> AsyncSystem<'a> for Accelerate {
type SystemData = (WriteStorage<'a, Velocity>, ReadStorage<'a, Acceleration>); type SystemData = (WriteStorage<'a, Velocity>, ReadStorage<'a, Acceleration>);
type Future = futures::future::Ready<()>;


fn run(&mut self, (mut velocity, acceleration): Self::SystemData) {
fn run(&mut self, (mut velocity, acceleration): Self::SystemData) -> Self::Future {
for (velocity, acceleration) in (&mut velocity, &acceleration).join() { for (velocity, acceleration) in (&mut velocity, &acceleration).join() {
velocity.x += acceleration.x; velocity.x += acceleration.x;
velocity.y += acceleration.y; velocity.y += acceleration.y;
} }


futures::future::ready(())

/* /*
use specs::{prelude::ParallelIterator, ParJoin}; use specs::{prelude::ParallelIterator, ParJoin};




+ 80
- 2
async-ecs/src/system/mod.rs Vedi File

@@ -1,15 +1,21 @@
mod system_data; mod system_data;


pub use system_data::{DynamicSystemData, SystemData};
pub use system_data::{DynamicSystemData, SystemData, WithSystemData};

use futures::future::{ready, Future, Ready};


use crate::{ use crate::{
access::{Accessor, AccessorCow, AccessorType}, access::{Accessor, AccessorCow, AccessorType},
world::World, world::World,
}; };


pub trait System<'a> {
/* System */

pub trait System<'a>: Sized {
type SystemData: DynamicSystemData<'a>; type SystemData: DynamicSystemData<'a>;


fn init(&mut self) {}

fn run(&mut self, data: Self::SystemData); fn run(&mut self, data: Self::SystemData);


fn accessor<'b>(&'b self) -> AccessorCow<'a, 'b, Self> { fn accessor<'b>(&'b self) -> AccessorCow<'a, 'b, Self> {
@@ -19,6 +25,8 @@ pub trait System<'a> {
} }


fn setup(&mut self, world: &mut World) { fn setup(&mut self, world: &mut World) {
self.init();

<Self::SystemData as DynamicSystemData>::setup(&self.accessor(), world) <Self::SystemData as DynamicSystemData>::setup(&self.accessor(), world)
} }


@@ -29,3 +37,73 @@ pub trait System<'a> {
let _ = world; let _ = world;
} }
} }

/* AsyncSystem */

pub trait AsyncSystem<'a>: Sized {
type SystemData: DynamicSystemData<'a>;
type Future: Future<Output = ()> + Send + 'a;

fn init(&mut self) {}

fn run(&mut self, data: Self::SystemData) -> Self::Future;

fn accessor<'b>(&'b self) -> AccessorCow<'a, 'b, Self> {
AccessorCow::Owned(
AccessorType::<'a, Self>::try_new().expect("Missing implementation for `accessor`"),
)
}

fn setup(&mut self, world: &mut World) {
self.init();

<Self::SystemData as DynamicSystemData>::setup(&self.accessor(), world)
}

fn dispose(self, world: &mut World)
where
Self: Sized,
{
let _ = world;
}
}

impl<'a, T> AsyncSystem<'a> for T
where
T: System<'a>,
{
type SystemData = T::SystemData;
type Future = Ready<()>;

fn init(&mut self) {
T::init(self);
}

fn run(&mut self, data: Self::SystemData) -> Self::Future {
T::run(self, data);

ready(())
}

fn accessor<'b>(&'b self) -> AccessorCow<'a, 'b, Self> {
T::accessor(self)
}

fn setup(&mut self, world: &mut World) {
T::setup(self, world)
}

fn dispose(self, world: &mut World)
where
Self: Sized,
{
T::dispose(self, world)
}
}

impl<'a, T> WithSystemData<'a> for T
where
T: AsyncSystem<'a>,
{
type SystemData = <T as AsyncSystem<'a>>::SystemData;
}

+ 4
- 0
async-ecs/src/system/system_data.rs Vedi File

@@ -24,6 +24,10 @@ pub trait DynamicSystemData<'a> {
fn fetch(access: &Self::Accessor, world: &'a World) -> Self; fn fetch(access: &Self::Accessor, world: &'a World) -> Self;
} }


pub trait WithSystemData<'a> {
type SystemData: DynamicSystemData<'a>;
}

/* SystemData */ /* SystemData */


impl<'a, T> SystemData<'a> for PhantomData<T> impl<'a, T> SystemData<'a> for PhantomData<T>


Caricamento…
Annulla
Salva