Quellcode durchsuchen

Implemented async systems

master
Bergmann89 vor 3 Jahren
Ursprung
Commit
3658c9322a
8 geänderte Dateien mit 122 neuen und 24 gelöschten Zeilen
  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 Datei anzeigen

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


+ 5
- 4
async-ecs/src/access/accessor.rs Datei anzeigen

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

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

pub trait Accessor: Sized {
@@ -28,14 +28,15 @@ pub struct StaticAccessor<T> {
pub enum AccessorCow<'a, 'b, T>
where
AccessorType<'a, T>: 'b,
T: System<'a> + ?Sized,
T: WithSystemData<'a> + ?Sized,
'a: 'b,
{
Borrow(&'b 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 */

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


+ 9
- 5
async-ecs/src/dispatcher/builder.rs Datei anzeigen

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

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};

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

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

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

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

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

#[test]
fn dependencies_on_read_and_write() {


+ 13
- 6
async-ecs/src/dispatcher/dispatchable.rs Datei anzeigen

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

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

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

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

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
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 Datei anzeigen

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

+ 9
- 6
async-ecs/src/main.rs Datei anzeigen

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

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 log::info;
@@ -71,8 +71,8 @@ async fn run() -> Result<(), Error> {
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)]
#[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 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() {
velocity.x += acceleration.x;
velocity.y += acceleration.y;
}

futures::future::ready(())

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



+ 80
- 2
async-ecs/src/system/mod.rs Datei anzeigen

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

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

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

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

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

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

fn init(&mut self) {}

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

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

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

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

@@ -29,3 +37,73 @@ pub trait System<'a> {
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 Datei anzeigen

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

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

/* SystemData */

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


Laden…
Abbrechen
Speichern