oxygengine_core/ecs/pipeline/engines/
default.rs1use 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}