oxygengine_core/ecs/pipeline/engines/
default.rs

1use crate::ecs::{
2    pipeline::{PipelineEngine, PipelineGraph},
3    Universe,
4};
5
6#[derive(Debug, Default, Clone, PartialEq)]
7pub struct DefaultPipelineEngine {
8    pub parallel: bool,
9    pub(crate) graph: Option<PipelineGraph>,
10}
11
12impl DefaultPipelineEngine {
13    pub fn with_parallel(mut self, mode: bool) -> Self {
14        self.parallel = mode;
15        self
16    }
17
18    fn run_node(node: &PipelineGraph, universe: &mut Universe) {
19        match node {
20            PipelineGraph::System(system) => (system.system)(universe),
21            PipelineGraph::Sequence(list) | PipelineGraph::Parallel(list) => {
22                for item in list {
23                    Self::run_node(item, universe);
24                }
25            }
26        }
27    }
28
29    #[cfg(feature = "parallel")]
30    fn run_node_parallel(node: &PipelineGraph, universe: &Universe) {
31        #[allow(mutable_transmutes)]
32        match node {
33            PipelineGraph::System(system) =>
34            {
35                #[allow(clippy::transmute_ptr_to_ptr)]
36                (system.system)(unsafe { std::mem::transmute(universe) })
37            }
38            PipelineGraph::Sequence(list) => {
39                for item in list {
40                    Self::run_node_parallel(item, universe);
41                }
42            }
43            PipelineGraph::Parallel(list) => {
44                if list.len() > 1 {
45                    use rayon::prelude::*;
46                    for item in list {
47                        if item.is_lock_on_single_thread() {
48                            #[allow(clippy::transmute_ptr_to_ptr)]
49                            Self::run_node(item, unsafe { std::mem::transmute(universe) });
50                        }
51                    }
52                    list.par_iter().for_each(|item| {
53                        if !item.is_lock_on_single_thread() {
54                            Self::run_node_parallel(item, universe)
55                        }
56                    });
57                } else {
58                    let item = list.first().unwrap();
59                    if item.is_lock_on_single_thread() {
60                        #[allow(clippy::transmute_ptr_to_ptr)]
61                        Self::run_node(item, unsafe { std::mem::transmute(universe) });
62                    } else {
63                        Self::run_node_parallel(item, universe);
64                    }
65                }
66            }
67        }
68    }
69}
70
71impl PipelineEngine for DefaultPipelineEngine {
72    fn setup(&mut self, graph: PipelineGraph) {
73        self.graph = Some(graph);
74    }
75
76    fn run(&self, universe: &mut Universe) {
77        #[cfg(not(feature = "parallel"))]
78        {
79            if let Some(node) = &self.graph {
80                Self::run_node(node, universe);
81            }
82        }
83        #[cfg(feature = "parallel")]
84        {
85            if let Some(node) = &self.graph {
86                if self.parallel {
87                    Self::run_node_parallel(node, universe);
88                } else {
89                    Self::run_node(node, universe);
90                }
91            }
92        }
93    }
94}