specs_task/
runner.rs

1use crate::{TaskComponent, TaskProgress};
2
3use specs::prelude::*;
4use std::marker::PhantomData;
5
6/// The counterpart to an implementation `TaskComponent`. Runs tasks until completion.
7///
8/// See the tests for usage.
9pub struct TaskRunnerSystem<T> {
10    marker: PhantomData<T>,
11}
12
13impl<T> Default for TaskRunnerSystem<T> {
14    fn default() -> Self {
15        TaskRunnerSystem {
16            marker: PhantomData,
17        }
18    }
19}
20
21impl<'a, T> System<'a> for TaskRunnerSystem<T>
22where
23    T: TaskComponent<'a>,
24{
25    // Note that we can only achieve task parallelism if `T::Data` does not have mutable overlap
26    // with other `TaskComponent::Data`.
27    type SystemData = (ReadStorage<'a, TaskProgress>, WriteStorage<'a, T>, T::Data);
28
29    fn run(&mut self, (progress, mut tasks, mut task_data): Self::SystemData) {
30        for (task_progress, task) in (&progress, &mut tasks).join() {
31            if !task_progress.is_unblocked() || task_progress.is_complete() {
32                continue;
33            }
34            let is_complete = task.run(&mut task_data);
35            if is_complete {
36                task_progress.complete();
37            }
38        }
39    }
40}