13 unstable releases (3 breaking)

0.4.0 Jun 16, 2020
0.3.0 Jun 5, 2020
0.2.1 May 20, 2020
0.1.8 Feb 1, 2020
0.1.7 Jan 23, 2020

#836 in Game dev

MIT license

44KB
787 lines

Fork-join multitasking for SPECS ECS

Instead of hand-rolling state machines to sequence the effects of various ECS systems, spawn tasks as entities and declare explicit temporal dependencies between them.

Code Examples

Making task graphs

fn make_static_task_graph(user: &TaskUser) {
    // Any component that implements TaskComponent can be spawned.
    let task_graph: TaskGraph = seq!(
        @TaskFoo("hello"),
        fork!(
            @TaskBar { value: 1 },
            @TaskBar { value: 2 },
            @TaskBar { value: 3 }
        ),
        @TaskZing("goodbye")
    );
    task_graph.assemble(user, OnCompletion::Delete);
}

fn make_dynamic_task_graph(user: &TaskUser) {
    let first = task!(@TaskFoo("hello"));
    let mut middle = empty_graph!();
    for i in 0..10 {
        middle = fork!(middle, @TaskBar { value: i });
    }
    let last = task!(@TaskZing("goodbye"));
    let task_graph: TaskGraph = seq!(first, middle, last);
    task_graph.assemble(user, OnCompletion::Delete);
}

Building a dispatcher with a TaskRunnerSystem

#[derive(Clone, Debug)]
struct PushValue {
    value: usize,
}

impl Component for PushValue {
    type Storage = VecStorage<Self>;
}

impl<'a> TaskComponent<'a> for PushValue {
    type Data = Write<'a, Vec<usize>>;

    fn run(&mut self, data: &mut Self::Data) -> bool {
        data.push(self.value);

        true
    }
}

fn make_dispatcher() -> Dispatcher {
    DispatcherBuilder::new()
        .with(
            TaskRunnerSystem::<PushValue>::default(),
            "push_value",
            &[],
        )
        .with(
            TaskManagerSystem,
            "task_manager",
            &[],
        )
        .build()
}

Dependencies

~4.5MB
~84K SLoC