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::type_id::TypeId;
8use crate::world::World;
9use alloc::boxed::Box;
10use alloc::vec::Vec;
11
12/// Self contained system that may be inserted into a [`Workload`].
13///
14/// ### Example:
15///
16/// ```rust
17/// use shipyard::{Component, 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 require_in_workload: DedupedLabels,
60    #[allow(missing_docs)]
61    pub require_before: DedupedLabels,
62    #[allow(missing_docs)]
63    pub require_after: DedupedLabels,
64}
65
66impl Extend<WorkloadSystem> for Workload {
67    fn extend<T: IntoIterator<Item = WorkloadSystem>>(&mut self, iter: T) {
68        self.systems.extend(iter);
69    }
70}
71
72#[allow(clippy::type_complexity)]
73pub struct RunIf {
74    pub(crate) system_fn: Box<dyn Fn(&World) -> Result<bool, error::Run> + Send + Sync + 'static>,
75}
76
77pub trait WorkloadRunIfFn: Send + Sync + 'static {
78    fn run(&self, world: &'_ World) -> Result<bool, error::Run>;
79    fn clone(&self) -> Box<dyn WorkloadRunIfFn>;
80}
81
82impl<F: Fn(&World) -> Result<bool, error::Run> + Clone + Send + Sync + 'static> WorkloadRunIfFn
83    for F
84{
85    fn run(&self, world: &'_ World) -> Result<bool, error::Run> {
86        (self)(world)
87    }
88
89    fn clone(&self) -> Box<dyn WorkloadRunIfFn> {
90        Box::new(self.clone())
91    }
92}
93
94#[allow(clippy::type_complexity)]
95pub(crate) trait ExtractWorkloadRunIf {
96    fn to_non_clone(
97        self,
98    ) -> Box<dyn Fn(&World) -> Result<bool, error::Run> + Send + Sync + 'static>;
99}
100
101impl ExtractWorkloadRunIf for Box<dyn WorkloadRunIfFn> {
102    fn to_non_clone(
103        self,
104    ) -> Box<dyn Fn(&World) -> Result<bool, error::Run> + Send + Sync + 'static> {
105        Box::new(move |world| self.run(world))
106    }
107}
108
109impl Clone for Box<dyn WorkloadRunIfFn> {
110    fn clone(&self) -> Box<dyn WorkloadRunIfFn> {
111        WorkloadRunIfFn::clone(&**self)
112    }
113}