shipyard/scheduler/
system.rs

1use super::TypeInfo;
2use crate::all_storages::AllStorages;
3use crate::error;
4use crate::scheduler::info::DedupedLabels;
5use crate::scheduler::label::Label;
6use crate::scheduler::workload::Workload;
7use crate::world::World;
8use alloc::boxed::Box;
9use alloc::vec::Vec;
10use core::any::TypeId;
11
12/// Self contained system that may be inserted into a [`Workload`].
13///
14/// ### Example:
15///
16/// ```rust
17/// use shipyard::{Component, scheduler::IntoWorkloadSystem, View, Workload, scheduler::WorkloadSystem, World};
18///
19/// #[derive(Component)]
20/// struct U32(u32);
21///
22/// #[derive(Component)]
23/// struct USIZE(usize);
24///
25/// fn sys1(u32s: View<U32>) {}
26/// fn sys2(usizes: View<USIZE>) {}
27///
28/// let workload_sys1: WorkloadSystem = sys1.into_workload_system().unwrap();
29///
30/// let mut workload = Workload::new("my_workload")
31///     .with_system(workload_sys1)
32///     .with_system(sys2);
33/// ```
34///
35/// [`Workload`]: crate::Workload
36#[allow(clippy::type_complexity)]
37pub struct WorkloadSystem {
38    #[allow(missing_docs)]
39    pub type_id: TypeId,
40    #[allow(missing_docs)]
41    pub display_name: Box<dyn Label>,
42    #[allow(missing_docs)]
43    pub system_fn: Box<dyn Fn(&World) -> Result<(), error::Run> + Send + Sync + 'static>,
44    /// access information
45    pub borrow_constraints: Vec<TypeInfo>,
46    /// Generates the tracking to enable for this system's views
47    pub tracking_to_enable: Vec<fn(&AllStorages) -> Result<(), error::GetStorage>>,
48    /// Generates constraints and system type id
49    pub generator: Box<dyn Fn(&mut Vec<TypeInfo>) -> TypeId + Send + Sync + 'static>,
50    #[allow(missing_docs)]
51    pub run_if: Option<Box<dyn Fn(&World) -> Result<bool, error::Run> + Send + Sync + 'static>>,
52    #[allow(missing_docs)]
53    pub tags: Vec<Box<dyn Label>>,
54    #[allow(missing_docs)]
55    pub before_all: DedupedLabels,
56    #[allow(missing_docs)]
57    pub after_all: DedupedLabels,
58    #[allow(missing_docs)]
59    pub after: Vec<usize>,
60    #[allow(missing_docs)]
61    pub before: Vec<usize>,
62    #[allow(missing_docs)]
63    pub unique_id: usize,
64    #[allow(missing_docs)]
65    pub require_in_workload: DedupedLabels,
66    #[allow(missing_docs)]
67    pub require_before: DedupedLabels,
68    #[allow(missing_docs)]
69    pub require_after: DedupedLabels,
70}
71
72impl Extend<WorkloadSystem> for Workload {
73    fn extend<T: IntoIterator<Item = WorkloadSystem>>(&mut self, iter: T) {
74        self.systems.extend(iter);
75    }
76}
77
78#[allow(clippy::type_complexity)]
79pub struct RunIf {
80    pub(crate) system_fn: Box<dyn Fn(&World) -> Result<bool, error::Run> + Send + Sync + 'static>,
81}
82
83pub trait WorkloadRunIfFn: Send + Sync + 'static {
84    fn run(&self, world: &'_ World) -> Result<bool, error::Run>;
85    fn clone(&self) -> Box<dyn WorkloadRunIfFn>;
86}
87
88impl<F: Fn(&World) -> Result<bool, error::Run> + Clone + Send + Sync + 'static> WorkloadRunIfFn
89    for F
90{
91    fn run(&self, world: &'_ World) -> Result<bool, error::Run> {
92        (self)(world)
93    }
94
95    fn clone(&self) -> Box<dyn WorkloadRunIfFn> {
96        Box::new(self.clone())
97    }
98}
99
100#[allow(clippy::type_complexity)]
101pub(crate) trait ExtractWorkloadRunIf {
102    fn to_non_clone(
103        self,
104    ) -> Box<dyn Fn(&World) -> Result<bool, error::Run> + Send + Sync + 'static>;
105}
106
107impl ExtractWorkloadRunIf for Box<dyn WorkloadRunIfFn> {
108    fn to_non_clone(
109        self,
110    ) -> Box<dyn Fn(&World) -> Result<bool, error::Run> + Send + Sync + 'static> {
111        Box::new(move |world| self.run(world))
112    }
113}
114
115impl Clone for Box<dyn WorkloadRunIfFn> {
116    fn clone(&self) -> Box<dyn WorkloadRunIfFn> {
117        WorkloadRunIfFn::clone(&**self)
118    }
119}