Skip to content

Commit

Permalink
Added documentation to the dispatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
AnneKitsune committed Jul 20, 2020
1 parent 3e40036 commit a0d893a
Showing 1 changed file with 45 additions and 1 deletion.
46 changes: 45 additions & 1 deletion amethyst_core/src/dispatcher.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::{ecs::prelude::*, ArcThreadPool};
use std::collections::BTreeMap;

/// A SystemBundle is a structure that can add multiple systems at once to a dispatcher.
pub trait SystemBundle {
fn build(
self,
Expand Down Expand Up @@ -29,6 +30,7 @@ impl SystemBundle
}
}

/// A bundle inserted going to be consumed by a dispatcher builder.
pub struct DispatcherSystemBundle<B>(B);
impl<B: SystemBundle> ConsumeDesc for DispatcherSystemBundle<B> {
fn consume(
Expand All @@ -43,6 +45,7 @@ impl<B: SystemBundle> ConsumeDesc for DispatcherSystemBundle<B> {
}
}

/// A system inserted in a dispatcher builder.
pub struct DispatcherSystem<F>(RelativeStage, F);
impl<F> ConsumeDesc for DispatcherSystem<F>
where
Expand All @@ -67,6 +70,7 @@ where
}
}

/// A thread local system in a dispatcher builder.
pub struct DispatcherThreadLocalSystem<F>(F);
impl<F> ConsumeDesc for DispatcherThreadLocalSystem<F>
where
Expand All @@ -87,6 +91,7 @@ where
}
}

/// A thread local in a dispatcher builder.
pub struct DispatcherThreadLocal<F>(F);
impl<F> ConsumeDesc for DispatcherThreadLocal<F>
where
Expand All @@ -103,6 +108,8 @@ where
Ok(())
}
}

/// Something that can be consumed by the DispatcherBuilder.
pub trait ConsumeDesc {
fn consume(
self: Box<Self>,
Expand All @@ -113,6 +120,7 @@ pub trait ConsumeDesc {
) -> Result<(), amethyst_error::Error>;
}

/// Something that runs on a local (main) thread.
pub trait ThreadLocal {
fn run(&mut self, world: &mut World, resources: &mut Resources);
fn dispose(self: Box<Self>, world: &mut World, resources: &mut Resources);
Expand All @@ -136,13 +144,15 @@ impl Into<Box<dyn ThreadLocal>> for Box<dyn Runnable> {
}
}

/// An object to be built as a thread local.
pub struct ThreadLocalObject<S, F, D>(pub S, pub F, pub D);
impl<S, F, D> ThreadLocalObject<S, F, D>
where
S: 'static,
F: FnMut(&mut S, &mut World, &mut Resources) + 'static,
D: FnOnce(S, &mut World, &mut Resources) + 'static,
{
/// Build the thread local object.
pub fn build(initial_state: S, run_fn: F, dispose_fn: D) -> Box<dyn ThreadLocal> {
Box::new(Self(initial_state, run_fn, dispose_fn))
}
Expand All @@ -161,10 +171,12 @@ where
}
}

/// Converts the type into a relative stage.
pub trait IntoRelativeStage: Copy {
fn into_relative(self) -> RelativeStage;
}

/// The default relative execution stages provided by amethyst.
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash, serde::Serialize, serde::Deserialize,
)]
Expand All @@ -180,13 +192,22 @@ impl IntoRelativeStage for Stage {
}
}

/// A relative execution stage.
/// Used for system execution ordering.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct RelativeStage(pub Stage, pub isize);
pub struct RelativeStage(
/// The internal execution stage.
pub Stage,
/// The stage offset.
pub isize,
);
impl RelativeStage {
/// Get the stage.
pub fn stage(&self) -> Stage {
self.0
}

/// Get the stage offset
pub fn offset(&self) -> isize {
self.1
}
Expand Down Expand Up @@ -214,21 +235,27 @@ impl Ord for RelativeStage {
}
}

/// A System execution dispatcher.
pub struct Dispatcher {
executor: Executor,
/// The defragmentation budget.
pub defrag_budget: Option<usize>,
pub(crate) thread_locals: Vec<Box<dyn ThreadLocal>>,
}
impl Dispatcher {
/// Execute the systems.
pub fn dispatch(&mut self, world: &mut World, resources: &mut Resources) {
self.executor.execute(world, resources);

self.thread_locals
.iter_mut()
.for_each(|local| local.run(world, resources));

// TODO: should we be using this?
//world.defrag(self.defrag_budget);
}

/// Clean and destroy the systems.
pub fn dispose(mut self, world: &mut World, resources: &mut Resources) {
self.thread_locals
.drain(..)
Expand All @@ -241,13 +268,16 @@ impl Dispatcher {
}
}

/// Data used by the Dispatcher.
#[derive(Default)]
pub struct DispatcherData {
/// The defragmentation budget.
pub defrag_budget: Option<usize>,
pub(crate) thread_locals: Vec<Box<dyn ThreadLocal>>,
pub(crate) stages: BTreeMap<RelativeStage, Vec<Box<dyn Schedulable>>>,
}
impl DispatcherData {
/// Flatten the DispatcherData into a Dispatcher.
pub fn flatten(mut self) -> Dispatcher {
let mut sorted_systems = Vec::with_capacity(128);
self.stages
Expand All @@ -270,6 +300,7 @@ impl DispatcherData {
}
}

/// Merge two DispatcherData together.
pub fn merge(mut self, mut other: DispatcherData) -> Self {
self.thread_locals.extend(other.thread_locals.drain(..));

Expand All @@ -284,6 +315,7 @@ impl DispatcherData {
}
}

/// A Dispatcher builder structure.
pub struct DispatcherBuilder<'a> {
pub(crate) defrag_budget: Option<usize>,
pub(crate) systems: Vec<(RelativeStage, Box<dyn ConsumeDesc + 'a>)>,
Expand All @@ -304,6 +336,7 @@ impl<'a> Default for DispatcherBuilder<'a> {
}
}
impl<'a> DispatcherBuilder<'a> {
/// Add a thread local resource.
pub fn add_thread_local<T: FnOnce(&mut World, &mut Resources) -> Box<dyn ThreadLocal> + 'a>(
&mut self,
desc: T,
Expand All @@ -312,6 +345,7 @@ impl<'a> DispatcherBuilder<'a> {
.push((Box::new(DispatcherThreadLocal(desc)) as Box<dyn ConsumeDesc>));
}

/// Add a thread local resource.
pub fn with_thread_local<T: FnOnce(&mut World, &mut Resources) -> Box<dyn ThreadLocal> + 'a>(
mut self,
desc: T,
Expand All @@ -321,6 +355,7 @@ impl<'a> DispatcherBuilder<'a> {
self
}

/// Add a thread local System.
pub fn add_thread_local_system<
T: FnOnce(&mut World, &mut Resources) -> Box<dyn Runnable> + 'a,
>(
Expand All @@ -331,6 +366,7 @@ impl<'a> DispatcherBuilder<'a> {
.push((Box::new(DispatcherThreadLocalSystem(desc)) as Box<dyn ConsumeDesc>));
}

/// Add a thread local System.
pub fn with_thread_local_system<
T: FnOnce(&mut World, &mut Resources) -> Box<dyn Runnable> + 'a,
>(
Expand All @@ -342,6 +378,7 @@ impl<'a> DispatcherBuilder<'a> {
self
}

/// Add a System.
pub fn add_system<
S: IntoRelativeStage,
T: FnOnce(&mut World, &mut Resources) -> Box<dyn Schedulable> + 'a,
Expand All @@ -356,6 +393,7 @@ impl<'a> DispatcherBuilder<'a> {
));
}

/// Add a System.
pub fn with_system<
S: IntoRelativeStage,
T: FnOnce(&mut World, &mut Resources) -> Box<dyn Schedulable> + 'a,
Expand All @@ -369,29 +407,34 @@ impl<'a> DispatcherBuilder<'a> {
self
}

/// Add a bundle to the dispatcher.
pub fn add_bundle<T: SystemBundle + 'a>(&mut self, bundle: T) {
self.bundles
.push(Box::new(DispatcherSystemBundle(bundle)) as Box<dyn ConsumeDesc>);
}

/// Add a bundle to the dispatcher.
pub fn with_bundle<T: SystemBundle + 'a>(mut self, bundle: T) -> Self {
self.add_bundle(bundle);

self
}

/// Set the defragmentation budget.
pub fn with_defrag_budget(mut self, budget: Option<usize>) -> Self {
self.defrag_budget = budget;

self
}

/// Set the thread pool.
pub fn with_pool(mut self, pool: Option<ArcThreadPool>) -> Self {
self.thread_pool = pool;

self
}

/// Is any system inserted?
pub fn is_empty(&self) -> bool {
self.systems.is_empty() && self.bundles.is_empty()
}
Expand Down Expand Up @@ -440,6 +483,7 @@ impl<'a> DispatcherBuilder<'a> {
dispatcher_data
}

/// Build the dispatcher!
pub fn build(mut self, world: &mut World, resources: &mut Resources) -> Dispatcher {
self.build_data(world, resources).flatten()
}
Expand Down

0 comments on commit a0d893a

Please sign in to comment.