1mod create_workload;
2
3use crate::all_storages::AllStorages;
4use crate::component::{Component, Unique};
5use crate::scheduler::info::{DedupedLabels, TypeInfo, WorkloadInfo};
6use crate::scheduler::label::WorkloadLabel;
7use crate::scheduler::system::{ExtractWorkloadRunIf, WorkloadRunIfFn};
8use crate::scheduler::{
9 AsLabel, Batches, IntoWorkload, IntoWorkloadSystem, IntoWorkloadTrySystem, Label, Scheduler,
10 WorkloadSystem,
11};
12use crate::storage::StorageId;
13use crate::unique::UniqueStorage;
14use crate::world::World;
15use crate::{error, ShipHashMap};
16use alloc::boxed::Box;
17use core::any::TypeId;
18use alloc::vec;
20use alloc::vec::Vec;
21use core::any::type_name;
22#[cfg(not(feature = "std"))]
23use core::any::Any;
24#[cfg(feature = "std")]
25use std::error::Error;
26
27#[allow(clippy::type_complexity)]
34pub struct ScheduledWorkload {
35 name: Box<dyn Label>,
36 #[allow(clippy::type_complexity)]
37 systems: Vec<Box<dyn Fn(&World) -> Result<(), error::Run> + Send + Sync + 'static>>,
38 system_names: Vec<Box<dyn Label>>,
39 #[allow(unused)]
40 system_generators: Vec<Box<dyn Fn(&mut Vec<TypeInfo>) -> TypeId + Send + Sync + 'static>>,
41 #[allow(unused)]
43 lookup_table: ShipHashMap<TypeId, usize>,
44 tracking_to_enable: Vec<fn(&AllStorages) -> Result<(), error::GetStorage>>,
45 batches: Batches,
46}
47
48impl ScheduledWorkload {
49 pub fn run_with_world(&self, world: &World) -> Result<(), error::RunWorkload> {
60 world.run_batches(&self.systems, &self.system_names, &self.batches, &self.name)
61 }
62
63 pub fn apply_tracking(&self, world: &World) -> Result<(), error::GetStorage> {
75 let all_storages = world
76 .all_storages()
77 .map_err(error::GetStorage::AllStoragesBorrow)?;
78
79 for enable_tracking_fn in &self.tracking_to_enable {
80 (enable_tracking_fn)(&all_storages)?;
81 }
82
83 Ok(())
84 }
85}
86
87impl World {
88 pub fn add_workload<Views, R, W, F: FnOnce() -> W + 'static>(&self, workload: F)
90 where
91 W: IntoWorkload<Views, R>,
92 {
93 let mut w = workload().into_workload();
94
95 w.tags.push(Box::new(WorkloadLabel {
96 type_id: TypeId::of::<F>(),
97 name: type_name::<F>().as_label(),
98 }));
99
100 w.name = if w.overwritten_name {
101 w.tags.push(w.name.clone());
102
103 w.name
104 } else {
105 Box::new(WorkloadLabel {
106 type_id: TypeId::of::<F>(),
107 name: type_name::<F>().as_label(),
108 })
109 };
110
111 w.add_to_world(self).unwrap();
112 }
113}
114
115pub struct Workload {
121 pub(super) name: Box<dyn Label>,
122 pub(super) tags: Vec<Box<dyn Label>>,
123 pub(super) systems: Vec<WorkloadSystem>,
124 pub(super) run_if: Option<Box<dyn WorkloadRunIfFn>>,
125 pub(super) before_all: DedupedLabels,
126 pub(super) after_all: DedupedLabels,
127 pub(super) overwritten_name: bool,
128 pub(super) require_before: DedupedLabels,
129 pub(super) require_after: DedupedLabels,
130 pub(super) barriers: Vec<usize>,
131}
132
133impl Workload {
134 pub fn new<T>(label: impl AsLabel<T>) -> Self {
176 let label = label.as_label();
177
178 Workload {
179 systems: Vec::new(),
180 name: label.clone(),
181 run_if: None,
182 tags: vec![label],
183 before_all: DedupedLabels::new(),
184 after_all: DedupedLabels::new(),
185 overwritten_name: true,
186 require_before: DedupedLabels::new(),
187 require_after: DedupedLabels::new(),
188 barriers: Vec::new(),
189 }
190 }
191 pub fn append(mut self, other: &mut Self) -> Self {
194 for system in &mut other.systems {
195 system.unique_id += self.systems.len();
196 }
197
198 self.systems.append(&mut other.systems);
199
200 self
201 }
202 pub fn merge(mut self, mut other: Workload) -> Workload {
205 self.propagate();
206 other.propagate();
207
208 let systems_len = self.systems.len();
209 self.barriers.extend(
210 other
211 .barriers
212 .drain(..)
213 .map(|barrier| barrier + systems_len),
214 );
215
216 self.append(&mut other)
217 }
218 fn propagate(&mut self) {
221 for system in &mut self.systems {
222 system.run_if = match (system.run_if.take(), self.run_if.clone()) {
223 (None, None) => None,
224 (None, Some(run_if)) => Some(run_if.to_non_clone()),
225 (Some(run_if), None) => Some(run_if),
226 (Some(system_run_if), Some(workload_run_if)) => Some(Box::new(move |world| {
227 Ok(workload_run_if.clone().run(world)? && (system_run_if)(world)?)
228 })),
229 };
230
231 system.tags.extend(self.tags.iter().cloned());
232
233 system.before_all.extend(self.before_all.iter().cloned());
234 system.after_all.extend(self.after_all.iter().cloned());
235 system
236 .require_before
237 .extend(self.require_before.iter().cloned());
238 system
239 .require_after
240 .extend(self.require_after.iter().cloned());
241 }
242
243 self.run_if = None;
244 self.tags.clear();
245 self.before_all.clear();
246 self.after_all.clear();
247 self.require_before.clear();
248 self.require_after.clear();
249 }
250 pub fn with_workload(self, other: Workload) -> Workload {
253 self.merge(other)
254 }
255 #[track_caller]
295 pub fn with_system<B, R, S: IntoWorkloadSystem<B, R>>(mut self, system: S) -> Workload {
296 let mut system = system.into_workload_system().unwrap();
297 system.unique_id += self.systems.len();
298
299 self.systems.push(system);
300
301 self
302 }
303 #[track_caller]
346 #[cfg(feature = "std")]
347 pub fn with_try_system<
348 B,
349 Ok,
350 Err: 'static + Into<Box<dyn Error + Send + Sync>>,
351 R: Into<Result<Ok, Err>>,
352 S: IntoWorkloadTrySystem<B, R>,
353 >(
354 mut self,
355 system: S,
356 ) -> Self {
357 let mut system = system.into_workload_try_system::<Ok, Err>().unwrap();
358 system.unique_id += self.systems.len();
359
360 self.systems.push(system);
361
362 self
363 }
364 #[track_caller]
401 #[cfg(not(feature = "std"))]
402 pub fn with_try_system<
403 B,
404 Ok,
405 Err: 'static + Send + Any,
406 R: Into<Result<Ok, Err>>,
407 S: IntoWorkloadTrySystem<B, R>,
408 >(
409 mut self,
410 system: S,
411 ) -> Self {
412 let mut system = system.into_workload_try_system::<Ok, Err>().unwrap();
413 system.unique_id += self.systems.len();
414
415 self.systems.push(system);
416
417 self
418 }
419 #[allow(clippy::blocks_in_conditions)]
436 pub fn add_to_world(self, world: &World) -> Result<(), error::AddWorkload> {
437 let Scheduler {
438 systems,
439 system_names,
440 system_generators,
441 lookup_table,
442 workloads,
443 workloads_info,
444 default,
445 } = &mut *world
446 .scheduler
447 .borrow_mut()
448 .map_err(|_| error::AddWorkload::Borrow)?;
449
450 let mut tracking_to_enable = Vec::new();
451
452 let name = self.name.dyn_clone();
453
454 let workload_info = create_workload::create_workload(
455 self,
456 systems,
457 system_names,
458 system_generators,
459 lookup_table,
460 &mut tracking_to_enable,
461 workloads,
462 default,
463 )?;
464
465 let all_storages = world
466 .all_storages()
467 .map_err(|_| error::AddWorkload::TrackingAllStoragesBorrow)?;
468
469 for enable_tracking_fn in &tracking_to_enable {
470 (enable_tracking_fn)(&all_storages).map_err(|err| match err {
471 error::GetStorage::StorageBorrow { name, id, borrow } => {
472 error::AddWorkload::TrackingStorageBorrow { name, id, borrow }
473 }
474 _ => unreachable!(),
475 })?;
476 }
477
478 workloads_info.insert(name, workload_info);
479
480 Ok(())
481 }
482 pub fn are_all_uniques_present_in_world(
489 &self,
490 world: &World,
491 ) -> Result<(), error::UniquePresence> {
492 struct ComponentType;
493
494 impl Component for ComponentType {
495 type Tracking = crate::track::Untracked;
496 }
497 impl Unique for ComponentType {}
498
499 let all_storages = world
500 .all_storages
501 .borrow()
502 .map_err(|_| error::UniquePresence::AllStorages)?;
503 let storages = all_storages.storages.read();
504
505 let unique_name = type_name::<UniqueStorage<ComponentType>>()
506 .split_once('<')
507 .unwrap()
508 .0;
509
510 for work_unit in &self.systems {
511 if let Some(value) = check_uniques_in_systems(work_unit, unique_name, &storages) {
512 return value;
513 }
514 }
515
516 Ok(())
517 }
518 pub fn build(self) -> Result<(ScheduledWorkload, WorkloadInfo), error::AddWorkload> {
520 let mut workload = ScheduledWorkload {
521 name: self.name.clone(),
522 systems: Vec::new(),
523 system_names: Vec::new(),
524 system_generators: Vec::new(),
525 lookup_table: ShipHashMap::new(),
526 tracking_to_enable: Vec::new(),
527 batches: Batches::default(),
528 };
529
530 let workload_name = self.name.clone();
531 let mut default: Box<dyn Label> = Box::new("");
532
533 let mut workloads = ShipHashMap::new();
534
535 let workload_info = create_workload::create_workload(
536 self,
537 &mut workload.systems,
538 &mut workload.system_names,
539 &mut workload.system_generators,
540 &mut workload.lookup_table,
541 &mut workload.tracking_to_enable,
542 &mut workloads,
543 &mut default,
544 )?;
545
546 workload.batches = workloads.remove(&workload_name).unwrap();
547
548 Ok((workload, workload_info))
549 }
550
551 pub fn with_barrier(mut self) -> Self {
553 self.barriers.push(self.systems.len());
554
555 self
556 }
557}
558
559fn check_uniques_in_systems(
560 system: &WorkloadSystem,
561 unique_name: &str,
562 storages: &ShipHashMap<StorageId, crate::storage::SBox>,
563) -> Option<Result<(), error::UniquePresence>> {
564 let WorkloadSystem {
565 borrow_constraints, ..
566 } = system;
567
568 for type_info in borrow_constraints {
569 if type_info.name.starts_with(unique_name) && !storages.contains_key(&type_info.storage_id)
570 {
571 return Some(Err(error::UniquePresence::Unique(type_info.clone())));
572 }
573 }
574
575 None
576}
577
578#[cfg(test)]
579mod tests {
580 use super::*;
581 use crate::component::{Component, Unique};
582 use crate::{
583 scheduler::Batches, scheduler::SystemModificator, scheduler::WorkloadModificator,
584 AllStoragesViewMut, IntoWorkload, UniqueView, UniqueViewMut, View, ViewMut, World,
585 };
586
587 struct Usize(usize);
588 #[allow(unused)]
589 struct U32(u32);
590 #[allow(unused)]
591 struct U16(u16);
592
593 impl Component for Usize {
594 type Tracking = crate::track::Untracked;
595 }
596 impl Component for U32 {
597 type Tracking = crate::track::Untracked;
598 }
599 impl Component for U16 {
600 type Tracking = crate::track::Untracked;
601 }
602 impl Unique for Usize {}
603 impl Unique for U32 {}
604 impl Unique for U16 {}
605
606 #[test]
607 fn single_immutable() {
608 fn system1(_: View<'_, Usize>) {}
609
610 let world = World::new();
611
612 Workload::new("System1")
613 .with_system(system1)
614 .add_to_world(&world)
615 .unwrap();
616
617 let scheduler = world.scheduler.borrow_mut().unwrap();
618 let label: Box<dyn Label> = Box::new("System1");
619 assert_eq!(scheduler.systems.len(), 1);
620 assert_eq!(scheduler.workloads.len(), 1);
621 assert_eq!(
622 scheduler.workloads.get(&label),
623 Some(&Batches {
624 parallel: vec![(None, vec![0])],
625 parallel_run_if: Vec::new(),
626 sequential: vec![0],
627 sequential_run_if: Vec::new(),
628 workload_run_if: None,
629 systems_run_if: Vec::new(),
630 })
631 );
632 assert_eq!(&scheduler.default, &label);
633 }
634
635 #[test]
636 fn single_mutable() {
637 fn system1(_: ViewMut<'_, Usize>) {}
638
639 let world = World::new();
640
641 Workload::new("System1")
642 .with_system(system1)
643 .add_to_world(&world)
644 .unwrap();
645
646 let scheduler = world.scheduler.borrow_mut().unwrap();
647 let label: Box<dyn Label> = Box::new("System1");
648 assert_eq!(scheduler.systems.len(), 1);
649 assert_eq!(scheduler.workloads.len(), 1);
650 assert_eq!(
651 scheduler.workloads.get(&label),
652 Some(&Batches {
653 parallel: vec![(None, vec![0])],
654 parallel_run_if: Vec::new(),
655 sequential: vec![0],
656 sequential_run_if: Vec::new(),
657 workload_run_if: None,
658 systems_run_if: Vec::new(),
659 })
660 );
661 assert_eq!(&scheduler.default, &label);
662 }
663
664 #[test]
665 fn multiple_immutable() {
666 fn system1(_: View<'_, Usize>) {}
667 fn system2(_: View<'_, Usize>) {}
668
669 let world = World::new();
670
671 Workload::new("Systems")
672 .with_system(system1)
673 .with_system(system2.into_workload_system().unwrap())
674 .add_to_world(&world)
675 .unwrap();
676
677 let scheduler = world.scheduler.borrow_mut().unwrap();
678 let label: Box<dyn Label> = Box::new("Systems");
679 assert_eq!(scheduler.systems.len(), 2);
680 assert_eq!(scheduler.workloads.len(), 1);
681 assert_eq!(
682 scheduler.workloads.get(&label),
683 Some(&Batches {
684 parallel: vec![(None, vec![0, 1])],
685 parallel_run_if: Vec::new(),
686 sequential: vec![0, 1],
687 sequential_run_if: Vec::new(),
688 workload_run_if: None,
689 systems_run_if: Vec::new(),
690 })
691 );
692 assert_eq!(&scheduler.default, &label);
693 }
694
695 #[test]
696 fn multiple_mutable() {
697 fn system1(_: ViewMut<'_, Usize>) {}
698 fn system2(_: ViewMut<'_, Usize>) {}
699
700 let world = World::new();
701
702 Workload::new("Systems")
703 .with_system(system1)
704 .with_system(system2)
705 .add_to_world(&world)
706 .unwrap();
707
708 let scheduler = world.scheduler.borrow_mut().unwrap();
709 let label: Box<dyn Label> = Box::new("Systems");
710 assert_eq!(scheduler.systems.len(), 2);
711 assert_eq!(scheduler.workloads.len(), 1);
712 assert_eq!(
713 scheduler.workloads.get(&label),
714 Some(&Batches {
715 parallel: vec![(None, vec![0]), (None, vec![1])],
716 parallel_run_if: Vec::new(),
717 sequential: vec![0, 1],
718 sequential_run_if: Vec::new(),
719 workload_run_if: None,
720 systems_run_if: Vec::new(),
721 })
722 );
723 assert_eq!(&scheduler.default, &label);
724 }
725
726 #[test]
727 fn multiple_mixed() {
728 fn system1(_: ViewMut<'_, Usize>) {}
729 fn system2(_: View<'_, Usize>) {}
730
731 let world = World::new();
732
733 Workload::new("Systems")
734 .with_system(system1)
735 .with_system(system2)
736 .add_to_world(&world)
737 .unwrap();
738
739 let scheduler = world.scheduler.borrow_mut().unwrap();
740 let label: Box<dyn Label> = Box::new("Systems");
741 assert_eq!(scheduler.systems.len(), 2);
742 assert_eq!(scheduler.workloads.len(), 1);
743 assert_eq!(
744 scheduler.workloads.get(&label),
745 Some(&Batches {
746 parallel: vec![(None, vec![0]), (None, vec![1])],
747 parallel_run_if: Vec::new(),
748 sequential: vec![0, 1],
749 sequential_run_if: Vec::new(),
750 workload_run_if: None,
751 systems_run_if: Vec::new(),
752 })
753 );
754 assert_eq!(&scheduler.default, &label);
755
756 let world = World::new();
757
758 Workload::new("Systems")
759 .with_system(system2)
760 .with_system(system1)
761 .add_to_world(&world)
762 .unwrap();
763
764 let scheduler = world.scheduler.borrow_mut().unwrap();
765 let label: Box<dyn Label> = Box::new("Systems");
766 assert_eq!(scheduler.systems.len(), 2);
767 assert_eq!(scheduler.workloads.len(), 1);
768 assert_eq!(
769 scheduler.workloads.get(&label),
770 Some(&Batches {
771 parallel: vec![(None, vec![0]), (None, vec![1])],
772 parallel_run_if: Vec::new(),
773 sequential: vec![0, 1],
774 sequential_run_if: Vec::new(),
775 workload_run_if: None,
776 systems_run_if: Vec::new(),
777 })
778 );
779 assert_eq!(&scheduler.default, &label);
780 }
781
782 #[test]
783 fn append_optimizes_batches() {
784 fn system_a1(_: View<'_, Usize>, _: ViewMut<'_, U32>) {}
785 fn system_a2(_: View<'_, Usize>, _: ViewMut<'_, U32>) {}
786 fn system_b1(_: View<'_, Usize>) {}
787
788 let world = World::new();
789
790 let mut group_a = Workload::new("Group A")
791 .with_system(system_a1)
792 .with_system(system_a2);
793
794 let mut group_b = Workload::new("Group B").with_system(system_b1);
795
796 Workload::new("Combined")
797 .append(&mut group_a)
798 .append(&mut group_b)
799 .add_to_world(&world)
800 .unwrap();
801
802 let scheduler = world.scheduler.borrow_mut().unwrap();
803 let label: Box<dyn Label> = Box::new("Combined");
804 assert_eq!(scheduler.systems.len(), 3);
805 assert_eq!(scheduler.workloads.len(), 1);
806 assert_eq!(
807 scheduler.workloads.get(&label),
808 Some(&Batches {
809 parallel: vec![(None, vec![0]), (None, vec![1, 2])],
810 parallel_run_if: Vec::new(),
811 sequential: vec![0, 1, 2],
812 sequential_run_if: Vec::new(),
813 workload_run_if: None,
814 systems_run_if: Vec::new(),
815 })
816 );
817 assert_eq!(&scheduler.default, &label);
818 }
819
820 #[test]
821 fn all_storages() {
822 fn system1(_: View<'_, Usize>) {}
823 fn system2(_: AllStoragesViewMut<'_>) {}
824
825 let world = World::new();
826
827 Workload::new("Systems")
828 .with_system(system2)
829 .add_to_world(&world)
830 .unwrap();
831
832 let scheduler = world.scheduler.borrow_mut().unwrap();
833 let label: Box<dyn Label> = Box::new("Systems");
834 assert_eq!(scheduler.systems.len(), 1);
835 assert_eq!(scheduler.workloads.len(), 1);
836 assert_eq!(
837 scheduler.workloads.get(&label),
838 Some(&Batches {
839 parallel: vec![(Some(0), Vec::new())],
840 parallel_run_if: Vec::new(),
841 sequential: vec![0],
842 sequential_run_if: Vec::new(),
843 workload_run_if: None,
844 systems_run_if: Vec::new(),
845 })
846 );
847 assert_eq!(&scheduler.default, &label);
848
849 let world = World::new();
850
851 Workload::new("Systems")
852 .with_system(system2)
853 .with_system(system2)
854 .add_to_world(&world)
855 .unwrap();
856
857 let scheduler = world.scheduler.borrow_mut().unwrap();
858 assert_eq!(scheduler.systems.len(), 1);
859 assert_eq!(scheduler.workloads.len(), 1);
860 assert_eq!(
861 scheduler.workloads.get(&label),
862 Some(&Batches {
863 parallel: vec![(Some(0), Vec::new()), (Some(0), Vec::new())],
864 parallel_run_if: Vec::new(),
865 sequential: vec![0, 0],
866 sequential_run_if: Vec::new(),
867 workload_run_if: None,
868 systems_run_if: Vec::new(),
869 })
870 );
871 assert_eq!(&scheduler.default, &label);
872
873 let world = World::new();
874
875 Workload::new("Systems")
876 .with_system(system1)
877 .with_system(system2)
878 .add_to_world(&world)
879 .unwrap();
880
881 let scheduler = world.scheduler.borrow_mut().unwrap();
882 let label: Box<dyn Label> = Box::new("Systems");
883 assert_eq!(scheduler.systems.len(), 2);
884 assert_eq!(scheduler.workloads.len(), 1);
885 assert_eq!(
886 scheduler.workloads.get(&label),
887 Some(&Batches {
888 parallel: vec![(None, vec![0]), (Some(1), Vec::new())],
889 parallel_run_if: Vec::new(),
890 sequential: vec![0, 1],
891 sequential_run_if: Vec::new(),
892 workload_run_if: None,
893 systems_run_if: Vec::new(),
894 })
895 );
896 assert_eq!(&scheduler.default, &label);
897
898 let world = World::new();
899
900 Workload::new("Systems")
901 .with_system(system2)
902 .with_system(system1)
903 .add_to_world(&world)
904 .unwrap();
905
906 let scheduler = world.scheduler.borrow_mut().unwrap();
907 assert_eq!(scheduler.systems.len(), 2);
908 assert_eq!(scheduler.workloads.len(), 1);
909 assert_eq!(
910 scheduler.workloads.get(&label),
911 Some(&Batches {
912 parallel: vec![(Some(0), Vec::new()), (None, vec![1])],
913 parallel_run_if: Vec::new(),
914 sequential: vec![0, 1],
915 sequential_run_if: Vec::new(),
916 workload_run_if: None,
917 systems_run_if: Vec::new(),
918 })
919 );
920 assert_eq!(&scheduler.default, &label);
921 }
922
923 #[cfg(feature = "thread_local")]
924 #[test]
925 fn non_send() {
926 use crate::borrow::NonSend;
927
928 #[allow(unused)]
929 struct NotSend(*const ());
930 unsafe impl Sync for NotSend {}
931 impl Component for NotSend {
932 type Tracking = crate::track::Untracked;
933 }
934
935 fn sys1(_: NonSend<View<'_, NotSend>>) {}
936 fn sys2(_: NonSend<ViewMut<'_, NotSend>>) {}
937 fn sys3(_: View<'_, Usize>) {}
938 fn sys4(_: ViewMut<'_, Usize>) {}
939
940 let world = World::new();
941
942 Workload::new("Test")
943 .with_system(sys1)
944 .with_system(sys1)
945 .add_to_world(&world)
946 .unwrap();
947
948 let scheduler = world.scheduler.borrow_mut().unwrap();
949 let label: Box<dyn Label> = Box::new("Test");
950 assert_eq!(scheduler.systems.len(), 1);
951 assert_eq!(scheduler.workloads.len(), 1);
952 assert_eq!(
953 scheduler.workloads.get(&label),
954 Some(&Batches {
955 parallel: vec![(None, vec![0, 0])],
956 parallel_run_if: Vec::new(),
957 sequential: vec![0, 0],
958 sequential_run_if: Vec::new(),
959 workload_run_if: None,
960 systems_run_if: Vec::new(),
961 })
962 );
963 assert_eq!(&scheduler.default, &label);
964 assert!(
965 scheduler.workloads_info[&label].batches_info[0].systems.1[0]
966 .conflict
967 .is_none()
968 );
969
970 let world = World::new();
971
972 Workload::new("Test")
973 .with_system(sys1)
974 .with_system(sys2)
975 .add_to_world(&world)
976 .unwrap();
977
978 let scheduler = world.scheduler.borrow_mut().unwrap();
979 assert_eq!(scheduler.systems.len(), 2);
980 assert_eq!(scheduler.workloads.len(), 1);
981 assert_eq!(
982 scheduler.workloads.get(&label),
983 Some(&Batches {
984 parallel: vec![(None, vec![0]), (Some(1), Vec::new())],
985 parallel_run_if: Vec::new(),
986 sequential: vec![0, 1],
987 sequential_run_if: Vec::new(),
988 workload_run_if: None,
989 systems_run_if: Vec::new(),
990 })
991 );
992 assert_eq!(&scheduler.default, &label);
993
994 let world = World::new();
995
996 Workload::new("Test")
997 .with_system(sys2)
998 .with_system(sys1)
999 .add_to_world(&world)
1000 .unwrap();
1001
1002 let scheduler = world.scheduler.borrow_mut().unwrap();
1003 assert_eq!(scheduler.systems.len(), 2);
1004 assert_eq!(scheduler.workloads.len(), 1);
1005 assert_eq!(
1006 scheduler.workloads.get(&label),
1007 Some(&Batches {
1008 parallel: vec![(Some(0), Vec::new()), (None, vec![1])],
1009 parallel_run_if: Vec::new(),
1010 sequential: vec![0, 1],
1011 sequential_run_if: Vec::new(),
1012 workload_run_if: None,
1013 systems_run_if: Vec::new(),
1014 })
1015 );
1016 assert_eq!(&scheduler.default, &label);
1017
1018 let world = World::new();
1019
1020 Workload::new("Test")
1021 .with_system(sys1)
1022 .with_system(sys3)
1023 .add_to_world(&world)
1024 .unwrap();
1025
1026 let scheduler = world.scheduler.borrow_mut().unwrap();
1027 assert_eq!(scheduler.systems.len(), 2);
1028 assert_eq!(scheduler.workloads.len(), 1);
1029 assert_eq!(
1030 scheduler.workloads.get(&label),
1031 Some(&Batches {
1032 parallel: vec![(None, vec![0, 1])],
1033 parallel_run_if: Vec::new(),
1034 sequential: vec![0, 1],
1035 sequential_run_if: Vec::new(),
1036 workload_run_if: None,
1037 systems_run_if: Vec::new(),
1038 })
1039 );
1040 assert_eq!(&scheduler.default, &label);
1041 assert!(
1042 scheduler.workloads_info[&label].batches_info[0].systems.1[0]
1043 .conflict
1044 .is_none()
1045 );
1046
1047 let world = World::new();
1048
1049 Workload::new("Test")
1050 .with_system(sys1)
1051 .with_system(sys4)
1052 .add_to_world(&world)
1053 .unwrap();
1054
1055 let scheduler = world.scheduler.borrow_mut().unwrap();
1056 assert_eq!(scheduler.systems.len(), 2);
1057 assert_eq!(scheduler.workloads.len(), 1);
1058 assert_eq!(
1059 scheduler.workloads.get(&label),
1060 Some(&Batches {
1061 parallel: vec![(None, vec![0, 1])],
1062 parallel_run_if: Vec::new(),
1063 sequential: vec![0, 1],
1064 sequential_run_if: Vec::new(),
1065 workload_run_if: None,
1066 systems_run_if: Vec::new(),
1067 })
1068 );
1069 assert_eq!(&scheduler.default, &label);
1070 }
1071
1072 #[test]
1073 fn unique_and_non_unique() {
1074 fn system1(_: ViewMut<'_, Usize>) {}
1075 fn system2(_: UniqueViewMut<'_, Usize>) {}
1076
1077 let world = World::new();
1078
1079 Workload::new("Systems")
1080 .with_system(system1)
1081 .with_system(system2)
1082 .add_to_world(&world)
1083 .unwrap();
1084
1085 let scheduler = world.scheduler.borrow_mut().unwrap();
1086 let label: Box<dyn Label> = Box::new("Systems");
1087 assert_eq!(scheduler.systems.len(), 2);
1088 assert_eq!(scheduler.workloads.len(), 1);
1089 assert_eq!(
1090 scheduler.workloads.get(&label),
1091 Some(&Batches {
1092 parallel: vec![(None, vec![0, 1])],
1093 parallel_run_if: Vec::new(),
1094 sequential: vec![0, 1],
1095 sequential_run_if: Vec::new(),
1096 workload_run_if: None,
1097 systems_run_if: Vec::new(),
1098 })
1099 );
1100 assert_eq!(&scheduler.default, &label);
1101 }
1102
1103 #[test]
1104 fn empty_workload() {
1105 let world = World::new();
1106
1107 Workload::new("Systems").add_to_world(&world).unwrap();
1108
1109 let scheduler = world.scheduler.borrow_mut().unwrap();
1110 let label: Box<dyn Label> = Box::new("Systems");
1111 assert_eq!(scheduler.systems.len(), 0);
1112 assert_eq!(scheduler.workloads.len(), 1);
1113 assert_eq!(
1114 scheduler.workloads.get(&label),
1115 Some(&Batches {
1116 parallel: vec![],
1117 parallel_run_if: Vec::new(),
1118 sequential: vec![],
1119 sequential_run_if: Vec::new(),
1120 workload_run_if: None,
1121 systems_run_if: Vec::new(),
1122 })
1123 );
1124 assert_eq!(&scheduler.default, &label);
1125 }
1126
1127 #[test]
1128 fn append_ensures_multiple_batches_can_be_optimized_over() {
1129 fn sys_a1(_: ViewMut<'_, Usize>, _: ViewMut<'_, U32>) {}
1130 fn sys_a2(_: View<'_, Usize>, _: ViewMut<'_, U32>) {}
1131 fn sys_b1(_: View<'_, Usize>) {}
1132 fn sys_c1(_: View<'_, U16>) {}
1133
1134 let world = World::new();
1135
1136 let mut group_a = Workload::new("Group A")
1137 .with_system(sys_a1)
1138 .with_system(sys_a2);
1139 let mut group_b = Workload::new("Group B").with_system(sys_b1);
1140 let mut group_c = Workload::new("Group C").with_system(sys_c1);
1141
1142 Workload::new("Combined")
1143 .append(&mut group_a)
1144 .append(&mut group_b)
1145 .append(&mut group_c)
1146 .add_to_world(&world)
1147 .unwrap();
1148
1149 let scheduler = world.scheduler.borrow_mut().unwrap();
1150 let label: Box<dyn Label> = Box::new("Combined");
1151 assert_eq!(scheduler.systems.len(), 4);
1152 assert_eq!(scheduler.workloads.len(), 1);
1153 assert_eq!(
1154 scheduler.workloads.get(&label),
1155 Some(&Batches {
1156 parallel: vec![(None, vec![0]), (None, vec![1, 2, 3])],
1157 parallel_run_if: Vec::new(),
1158 sequential: vec![0, 1, 2, 3],
1159 sequential_run_if: Vec::new(),
1160 workload_run_if: None,
1161 systems_run_if: Vec::new(),
1162 })
1163 );
1164 assert_eq!(&scheduler.default, &label);
1165 }
1166
1167 #[test]
1168 fn skip_if_missing_storage() {
1169 let world = World::new();
1170
1171 Workload::new("test")
1172 .skip_if_storage_empty::<Usize>()
1173 .with_system(|| panic!())
1174 .build()
1175 .unwrap()
1176 .0
1177 .run_with_world(&world)
1178 .unwrap();
1179
1180 Workload::new("test")
1181 .skip_if_storage_empty::<Usize>()
1182 .with_system(|| panic!())
1183 .add_to_world(&world)
1184 .unwrap();
1185
1186 world.run_default_workload().unwrap();
1187 }
1188
1189 #[test]
1190 fn system_skip_if_missing_storage() {
1191 let world = World::new();
1192
1193 Workload::new("test")
1194 .with_system((|| -> () { panic!() }).skip_if_storage_empty::<Usize>())
1195 .build()
1196 .unwrap()
1197 .0
1198 .run_with_world(&world)
1199 .unwrap();
1200
1201 Workload::new("test")
1202 .with_system((|| -> () { panic!() }).skip_if_storage_empty::<Usize>())
1203 .add_to_world(&world)
1204 .unwrap();
1205
1206 world.run_default_workload().unwrap();
1207 }
1208
1209 #[test]
1210 fn skip_if_empty_storage() {
1211 let mut world = World::new();
1212
1213 let eid = world.add_entity((Usize(0),));
1214 world.remove::<(Usize,)>(eid);
1215
1216 Workload::new("test")
1217 .skip_if_storage_empty::<Usize>()
1218 .with_system(|| -> () { panic!() })
1219 .build()
1220 .unwrap()
1221 .0
1222 .run_with_world(&world)
1223 .unwrap();
1224
1225 Workload::new("test")
1226 .skip_if_storage_empty::<Usize>()
1227 .with_system(|| -> () { panic!() })
1228 .add_to_world(&world)
1229 .unwrap();
1230
1231 world.run_default_workload().unwrap();
1232 }
1233
1234 #[test]
1235 fn system_skip_if_empty_storage() {
1236 let mut world = World::new();
1237
1238 let eid = world.add_entity((Usize(0),));
1239 world.remove::<(Usize,)>(eid);
1240
1241 Workload::new("test")
1242 .with_system((|| -> () { panic!() }).skip_if_storage_empty::<Usize>())
1243 .build()
1244 .unwrap()
1245 .0
1246 .run_with_world(&world)
1247 .unwrap();
1248
1249 Workload::new("test")
1250 .with_system((|| -> () { panic!() }).skip_if_storage_empty::<Usize>())
1251 .add_to_world(&world)
1252 .unwrap();
1253
1254 world.run_default_workload().unwrap();
1255 }
1256
1257 #[test]
1258 fn workload_merge_skip_if() {
1259 let world = World::new();
1260
1261 world.add_unique(Usize(0));
1262
1263 world.add_workload(|| {
1264 (
1265 (|| -> () { panic!() })
1266 .into_workload()
1267 .skip_if_missing_unique::<U32>(),
1268 (|mut u: UniqueViewMut<'_, Usize>| u.0 += 1).into_workload(),
1269 )
1270 });
1271
1272 world.run_default_workload().unwrap();
1273
1274 assert_eq!(world.borrow::<UniqueView<'_, Usize>>().unwrap().0, 1);
1275 }
1276
1277 #[test]
1278 fn before_after() {
1279 fn a() {}
1280 fn b() {}
1281 fn c() {}
1282 fn d() {}
1283
1284 let (workload, _) = Workload::new("")
1285 .with_system(d.after_all(b))
1286 .with_system(c.after_all(b))
1287 .with_system(b.after_all(a))
1288 .with_system(a)
1289 .build()
1290 .unwrap();
1291
1292 let batches = &workload.batches;
1293 assert_eq!(batches.sequential, &[3, 2, 0, 1]);
1294 assert_eq!(
1295 batches.parallel,
1296 &[(None, vec![3]), (None, vec![2]), (None, vec![0, 1])]
1297 );
1298
1299 let (workload, _) = Workload::new("")
1300 .with_system(a)
1301 .with_system(b.after_all(a))
1302 .with_system(c.after_all(b))
1303 .build()
1304 .unwrap();
1305
1306 let batches = &workload.batches;
1307 assert_eq!(batches.sequential, &[0, 1, 2]);
1308 assert_eq!(
1309 batches.parallel,
1310 &[(None, vec![0]), (None, vec![1]), (None, vec![2])]
1311 );
1312
1313 let (workload, _) = Workload::new("")
1314 .with_system(b.after_all(a))
1315 .with_system(a)
1316 .with_system(c.after_all(b))
1317 .build()
1318 .unwrap();
1319
1320 let batches = &workload.batches;
1321 assert_eq!(batches.sequential, &[1, 0, 2]);
1322 assert_eq!(
1323 batches.parallel,
1324 &[(None, vec![1]), (None, vec![0]), (None, vec![2])]
1325 );
1326 }
1327
1328 #[test]
1329 fn before_after_no_anchor() {
1330 fn a() {}
1331 fn b() {}
1332
1333 let (workload, _) = Workload::new("")
1334 .with_system(a.before_all(b))
1335 .with_system(b.after_all(a))
1336 .build()
1337 .unwrap();
1338
1339 let batches = &workload.batches;
1340 assert_eq!(batches.sequential, &[0, 1]);
1341 assert_eq!(batches.parallel, &[(None, vec![0]), (None, vec![1])]);
1342
1343 let (workload, _) = Workload::new("")
1344 .with_system(b.after_all(a))
1345 .with_system(a.before_all(b))
1346 .build()
1347 .unwrap();
1348
1349 let batches = &workload.batches;
1350 assert_eq!(batches.sequential, &[1, 0]);
1351 assert_eq!(batches.parallel, &[(None, vec![1]), (None, vec![0])]);
1352 }
1353
1354 #[test]
1355 fn before_after_missing_system() {
1356 fn a() {}
1357 fn b() {}
1358
1359 let (workload, _) = Workload::new("")
1360 .with_system(a.before_all(b))
1361 .build()
1362 .unwrap();
1363
1364 let batches = &workload.batches;
1365 assert_eq!(batches.sequential, &[0]);
1366 assert_eq!(batches.parallel, &[(None, vec![0])]);
1367 }
1368
1369 #[test]
1370 fn before_after_absent_system() {
1371 fn a() {}
1372 fn b() {}
1373 fn c() {}
1374
1375 let (workload, _) = Workload::new("")
1376 .with_system(a)
1377 .with_system(c.after_all(b))
1378 .build()
1379 .unwrap();
1380
1381 let batches = &workload.batches;
1383 assert!(batches.sequential == [0, 1] || batches.sequential == [1, 0]);
1384 assert_eq!(batches.parallel, &[(None, vec![0, 1])]);
1385 }
1386
1387 #[test]
1388 fn before_after_system_label() {
1389 fn a() {}
1390 fn b() {}
1391 fn c() {}
1392
1393 let (workload, _) = Workload::new("")
1394 .with_system(a.tag("a"))
1395 .with_system(
1396 b.tag("b")
1397 .before_all("a")
1398 .require_after("a")
1399 .require_before("c"),
1400 )
1401 .with_system(c.tag("c").before_all("b").require_after("b"))
1402 .build()
1403 .unwrap();
1404
1405 let batches = &workload.batches;
1406 assert_eq!(batches.sequential, &[2, 1, 0]);
1407 assert_eq!(
1408 batches.parallel,
1409 &[(None, vec![2]), (None, vec![1]), (None, vec![0])]
1410 );
1411
1412 let (workload, _) = Workload::new("")
1413 .with_system(c.tag("c").after_all("b"))
1414 .with_system(b.tag("b").after_all("a"))
1415 .with_system(a.tag("a"))
1416 .build()
1417 .unwrap();
1418
1419 let batches = &workload.batches;
1420 assert_eq!(batches.sequential, &[2, 1, 0]);
1421 assert_eq!(
1422 batches.parallel,
1423 &[(None, vec![2]), (None, vec![1]), (None, vec![0])]
1424 );
1425 }
1426
1427 #[test]
1428 fn after_all_single_system() {
1429 let (workload, _) = Workload::new("")
1430 .with_system((|| {}).tag("this"))
1431 .with_system((|_: AllStoragesViewMut<'_>| {}).after_all("this"))
1432 .with_system((|_: View<'_, Usize>| {}).after_all("this"))
1433 .build()
1434 .unwrap();
1435
1436 let batches = &workload.batches;
1437
1438 assert_eq!(
1439 batches,
1440 &Batches {
1441 parallel: vec![(None, vec![0]), (Some(1), vec![]), (None, vec![2])],
1442 parallel_run_if: Vec::new(),
1443 sequential: vec![0, 1, 2],
1444 sequential_run_if: Vec::new(),
1445 workload_run_if: None,
1446 systems_run_if: Vec::new()
1447 }
1448 );
1449 }
1450
1451 #[test]
1452 fn sequential_workload() {
1453 fn sys0() {}
1454 fn sys1() {}
1455 fn sys2() {}
1456 fn workload1() -> Workload {
1457 (sys0, sys1, sys2).into_sequential_workload()
1458 }
1459
1460 let (workload, _) = workload1().rename("").build().unwrap();
1461
1462 let batches = &workload.batches;
1463 assert_eq!(batches.sequential, &[0, 1, 2]);
1464 assert_eq!(
1465 batches.parallel,
1466 &[(None, vec![0]), (None, vec![1]), (None, vec![2])]
1467 );
1468 }
1469
1470 #[test]
1471 fn before_after_borrow_conflict() {
1472 fn sys0(_: View<'_, U32>) {}
1473 fn sys1(_: AllStoragesViewMut<'_>) {}
1474
1475 let (workload, _) = (sys0, sys1.before_all("not present"), sys0)
1476 .into_workload()
1477 .rename("")
1478 .build()
1479 .unwrap();
1480
1481 let batches = &workload.batches;
1482 assert_eq!(
1483 batches.parallel,
1484 &[(None, vec![0]), (Some(1), Vec::new()), (None, vec![0])]
1485 );
1486 assert_eq!(batches.sequential, &[0, 1, 0]);
1487 }
1488
1489 #[test]
1490 fn contains() {
1491 fn type_name_of<T: 'static>(_: &T) -> &'static str {
1492 type_name::<T>()
1493 }
1494 fn type_id_of<T: 'static>(_: &T) -> TypeId {
1495 TypeId::of::<T>()
1496 }
1497
1498 fn w() -> Workload {
1499 (|| {}).into_workload()
1500 }
1501 let world = World::builder()
1502 .with_custom_lock::<parking_lot::RawRwLock>()
1503 .build();
1504 world.add_workload(w);
1505 assert!(world.contains_workload(WorkloadLabel {
1506 type_id: type_id_of(&w),
1507 name: type_name_of(&w).as_label()
1508 }));
1509 assert!(world.contains_workload(w));
1510 world.run_workload(w).unwrap();
1511 }
1512
1513 #[test]
1514 fn barrier() {
1515 let workload = Workload::new("")
1516 .with_system(|| {})
1517 .with_system(|| {})
1518 .with_barrier()
1519 .with_system(|| {})
1520 .with_system(|| {})
1521 .with_barrier()
1522 .with_system(|| {})
1523 .with_system(|| {})
1524 .build()
1525 .unwrap();
1526
1527 assert_eq!(workload.1.batches_info.len(), 3);
1528
1529 let workload = Workload::new("")
1530 .with_barrier()
1531 .with_system(|| {})
1532 .with_system(|| {})
1533 .build()
1534 .unwrap();
1535
1536 assert_eq!(workload.1.batches_info.len(), 1);
1537
1538 let workload = Workload::new("")
1539 .with_system(|| {})
1540 .with_system(|| {})
1541 .with_barrier()
1542 .build()
1543 .unwrap();
1544
1545 assert_eq!(workload.1.batches_info.len(), 1);
1546 }
1547
1548 #[test]
1549 fn with_system_return_type() {
1550 Workload::new("").with_system(|| 0usize).build().unwrap();
1551 }
1552
1553 #[test]
1554 fn try_system_run_if() {
1555 fn try_sys() -> Result<(), error::MissingComponent> {
1556 Err(error::MissingComponent {
1557 id: crate::EntityId::dead(),
1558 name: "",
1559 })
1560 }
1561
1562 let (workload, _) = Workload::new("")
1563 .with_try_system(try_sys.into_workload_try_system().unwrap().run_if(|| true))
1564 .build()
1565 .unwrap();
1566
1567 let world = World::new();
1568
1569 assert!(workload
1570 .run_with_world(&world)
1571 .err()
1572 .unwrap()
1573 .custom_error()
1574 .is_some());
1575 }
1576
1577 #[test]
1579 fn cycle_detection_after_all() {
1580 fn sys_a() {}
1581 fn sys_b() {}
1582 fn workload_cycle() -> Workload {
1583 (sys_a.after_all(sys_b), sys_b.after_all(sys_a)).into_workload()
1584 }
1585
1586 let result = workload_cycle().build();
1587
1588 assert!(matches!(
1589 result,
1590 Err(error::AddWorkload::ImpossibleRequirements(
1591 error::ImpossibleRequirements::Cycle(_)
1592 ))
1593 ));
1594 }
1595
1596 #[test]
1601 fn cycle_detection_before_after_all() {
1602 fn sys_a() {}
1603 fn sys_b() {}
1604 fn sys_c() {}
1605 fn workload_cycle() -> Workload {
1606 (sys_a, sys_b, sys_c.before_all(sys_a).after_all(sys_b)).into_workload()
1607 }
1608
1609 let result = workload_cycle().build();
1610
1611 assert!(matches!(
1612 result,
1613 Err(error::AddWorkload::ImpossibleRequirements(_))
1614 ));
1615 }
1616
1617 #[test]
1619 fn cycle_barrier() {
1620 fn sys_a() {}
1621 fn sys_b() {}
1622
1623 let result = Workload::new("")
1624 .with_system(sys_a)
1625 .with_barrier()
1626 .with_system(sys_b.before_all(sys_a))
1627 .build();
1628
1629 assert!(matches!(
1630 result,
1631 Err(error::AddWorkload::ImpossibleRequirements(
1632 error::ImpossibleRequirements::Cycle(_)
1633 ))
1634 ));
1635 }
1636
1637 #[test]
1639 fn complex_ordering() {
1640 fn sys_a() {}
1641 fn sys_b() {}
1642 fn sys_c() {}
1643 fn sys_d() {}
1644
1645 let (workload, _) = Workload::new("")
1646 .with_system(sys_a)
1647 .with_system(sys_b)
1648 .with_system(sys_c.after_all(sys_a).before_all(sys_b))
1649 .with_barrier()
1650 .with_system(sys_d)
1651 .build()
1652 .unwrap();
1653
1654 let batches = &workload.batches;
1655 assert_eq!(
1656 batches.parallel,
1657 &[
1658 (None, vec![0]),
1659 (None, vec![2]),
1660 (None, vec![1]),
1661 (None, vec![3])
1662 ]
1663 );
1664 assert_eq!(batches.sequential, &[0, 2, 1, 3]);
1665 }
1666
1667 #[test]
1668 fn require_in_workload() {
1669 fn sys_a() {}
1670 fn sys_b() {}
1671 fn sys_c() {}
1672
1673 Workload::new("")
1674 .with_system(sys_a.require_in_workload(sys_b))
1675 .with_system(sys_b)
1676 .build()
1677 .unwrap();
1678 Workload::new("")
1679 .with_system(sys_a)
1680 .with_system(sys_b.require_in_workload(sys_a))
1681 .build()
1682 .unwrap();
1683
1684 let result = Workload::new("")
1685 .with_system(sys_c)
1686 .with_system(sys_a.require_in_workload(sys_b))
1687 .with_system(sys_c)
1688 .build();
1689
1690 assert_eq!(
1691 result.err(),
1692 Some(error::AddWorkload::MissingInWorkload(
1693 sys_a.as_label(),
1694 vec![sys_b.as_label()]
1695 ))
1696 );
1697 }
1698
1699 #[test]
1700 fn require_before() {
1701 fn sys_a() {}
1702 fn sys_b() {}
1703
1704 Workload::new("")
1705 .with_system(sys_a.after_all(sys_b).require_before(sys_b))
1706 .with_system(sys_b)
1707 .build()
1708 .unwrap();
1709 Workload::new("")
1710 .with_system(sys_a)
1711 .with_system(sys_b.after_all(sys_a).require_before(sys_a))
1712 .build()
1713 .unwrap();
1714 Workload::new("")
1715 .with_system(sys_a)
1716 .with_barrier()
1717 .with_system(sys_b.require_before(sys_a))
1718 .build()
1719 .unwrap();
1720 Workload::new("")
1721 .with_system((|_: AllStoragesViewMut<'_>| {}).tag("sys_a"))
1722 .with_system((|_: AllStoragesViewMut<'_>| {}).require_before("sys_a"))
1723 .build()
1724 .unwrap();
1725
1726 let result = Workload::new("")
1728 .with_system(sys_a)
1729 .with_system(sys_b.require_before(sys_a))
1730 .build();
1731
1732 assert_eq!(
1733 result.err(),
1734 Some(error::AddWorkload::MissingBefore(
1735 sys_b.as_label(),
1736 vec![sys_a.as_label()]
1737 ))
1738 );
1739 }
1740
1741 #[test]
1742 fn require_after() {
1743 fn sys_a() {}
1744 fn sys_b() {}
1745
1746 Workload::new("")
1747 .with_system(sys_a)
1748 .with_system(sys_b.before_all(sys_a).require_after(sys_a))
1749 .build()
1750 .unwrap();
1751 Workload::new("")
1752 .with_system(sys_a.before_all(sys_b).require_after(sys_b))
1753 .with_system(sys_b)
1754 .build()
1755 .unwrap();
1756 Workload::new("")
1757 .with_system(sys_a.require_after(sys_b))
1758 .with_barrier()
1759 .with_system(sys_b)
1760 .build()
1761 .unwrap();
1762 Workload::new("")
1763 .with_system((|_: AllStoragesViewMut<'_>| {}).require_after("sys_a"))
1764 .with_system((|_: AllStoragesViewMut<'_>| {}).tag("sys_a"))
1765 .build()
1766 .unwrap();
1767
1768 let result = Workload::new("")
1770 .with_system(sys_a.require_after(sys_b))
1771 .with_system(sys_b)
1772 .build();
1773
1774 assert_eq!(
1775 result.err(),
1776 Some(error::AddWorkload::MissingAfter(
1777 sys_a.as_label(),
1778 vec![sys_b.as_label()]
1779 ))
1780 );
1781 }
1782}
1783
1784#[cfg(test)]
1786mod info_tests {
1787 use super::*;
1788 use crate::borrow::Mutability;
1789 use crate::scheduler::info::{BeforeAfterConstraint, Conflict, SystemInfo};
1790 use crate::scheduler::system_modificator::SystemModificator;
1791 use crate::sparse_set::SparseSet;
1792 use crate::views::{View, ViewMut};
1793 use alloc::format;
1794 use std::string::ToString;
1795
1796 #[allow(unused)]
1797 struct Usize(usize);
1798 impl Component for Usize {
1799 type Tracking = crate::track::Untracked;
1800 }
1801 #[allow(unused)]
1802 struct U32(u32);
1803 impl Component for U32 {
1804 type Tracking = crate::track::Untracked;
1805 }
1806
1807 #[test]
1808 fn before_all() {
1809 fn sys_a() {}
1810 fn sys_b() {}
1811
1812 let (_, info) = Workload::new("workload 1")
1813 .with_system(sys_a)
1814 .with_system(sys_b.before_all(sys_a))
1815 .build()
1816 .unwrap();
1817
1818 assert_eq!(info.name, "workload 1");
1819 assert_eq!(info.batches_info.len(), 2);
1820
1821 let mut systems0 = info.batches_info[0].systems();
1822 assert_eq!(
1823 systems0.next(),
1824 Some(&SystemInfo {
1825 name: "System(shipyard::scheduler::workload::info_tests::before_all::sys_b)"
1826 .to_string(),
1827 borrow: vec![],
1828 conflict: None,
1829 after: vec![],
1830 after_all: vec![],
1831 before_all: vec![BeforeAfterConstraint {
1832 other_system: 0,
1833 constraint:
1834 "System(shipyard::scheduler::workload::info_tests::before_all::sys_a)"
1835 .to_string()
1836 }],
1837 unique_id: 1
1838 })
1839 );
1840 assert_eq!(systems0.next(), None);
1841
1842 let mut systems1 = info.batches_info[1].systems();
1843 assert_eq!(
1844 systems1.next(),
1845 Some(&SystemInfo {
1846 name: "System(shipyard::scheduler::workload::info_tests::before_all::sys_a)"
1847 .to_string(),
1848 borrow: vec![],
1849 conflict: None,
1850 after: vec![1],
1851 after_all: vec![],
1852 before_all: vec![],
1853 unique_id: 0
1854 })
1855 );
1856 assert_eq!(systems1.next(), None);
1857 }
1858
1859 #[test]
1860 fn after_all() {
1861 fn sys_a() {}
1862 fn sys_b() {}
1863
1864 let (_, info) = Workload::new("workload 1")
1865 .with_system(sys_a.after_all(sys_b))
1866 .with_system(sys_b)
1867 .build()
1868 .unwrap();
1869
1870 assert_eq!(info.name, "workload 1");
1871 assert_eq!(info.batches_info.len(), 2);
1872
1873 let mut systems0 = info.batches_info[0].systems();
1874 assert_eq!(
1875 systems0.next(),
1876 Some(&SystemInfo {
1877 name: "System(shipyard::scheduler::workload::info_tests::after_all::sys_b)"
1878 .to_string(),
1879 borrow: vec![],
1880 conflict: None,
1881 after: vec![],
1882 after_all: vec![],
1883 before_all: vec![],
1884 unique_id: 1
1885 })
1886 );
1887 assert_eq!(systems0.next(), None);
1888
1889 let mut systems1 = info.batches_info[1].systems();
1890 assert_eq!(
1891 systems1.next(),
1892 Some(&SystemInfo {
1893 name: "System(shipyard::scheduler::workload::info_tests::after_all::sys_a)"
1894 .to_string(),
1895 borrow: vec![],
1896 conflict: None,
1897 after: vec![1],
1898 after_all: vec![BeforeAfterConstraint {
1899 other_system: 1,
1900 constraint:
1901 "System(shipyard::scheduler::workload::info_tests::after_all::sys_b)"
1902 .to_string()
1903 }],
1904 before_all: vec![],
1905 unique_id: 0
1906 })
1907 );
1908 assert_eq!(systems1.next(), None);
1909 }
1910
1911 #[test]
1912 fn borrow() {
1913 fn sys_a(_: View<'_, Usize>, _: View<'_, U32>) {}
1914 fn sys_b(_: ViewMut<'_, Usize>, _: View<'_, U32>) {}
1915 fn sys_c(_: View<'_, Usize>) {}
1916 fn sys_d(_: View<'_, Usize>) {}
1917
1918 let (_, info) = Workload::new("")
1919 .with_system(sys_a)
1920 .with_system(sys_b)
1921 .with_system(sys_c)
1922 .with_system(sys_d)
1923 .build()
1924 .unwrap();
1925
1926 let mut systems0 = info.batches_info[0].systems();
1927 assert_eq!(
1928 systems0.next(),
1929 Some(&SystemInfo {
1930 name: format!("{:?}", sys_a.as_label()),
1931 borrow: vec![
1932 TypeInfo {
1933 name: type_name::<SparseSet::<Usize>>().into(),
1934 mutability: Mutability::Shared,
1935 storage_id: StorageId::of::<SparseSet<Usize>>(),
1936 thread_safe: true
1937 },
1938 TypeInfo {
1939 name: type_name::<SparseSet::<U32>>().into(),
1940 mutability: Mutability::Shared,
1941 storage_id: StorageId::of::<SparseSet<U32>>(),
1942 thread_safe: true
1943 }
1944 ],
1945 conflict: None,
1946 after: vec![],
1947 after_all: vec![],
1948 before_all: vec![],
1949 unique_id: 0
1950 })
1951 );
1952
1953 let mut systems1 = info.batches_info[1].systems();
1954 assert_eq!(
1955 systems1.next(),
1956 Some(&SystemInfo {
1957 name: format!("{:?}", sys_b.as_label()),
1958 borrow: vec![
1959 TypeInfo {
1960 name: type_name::<SparseSet::<Usize>>().into(),
1961 mutability: Mutability::Exclusive,
1962 storage_id: StorageId::of::<SparseSet<Usize>>(),
1963 thread_safe: true
1964 },
1965 TypeInfo {
1966 name: type_name::<SparseSet::<U32>>().into(),
1967 mutability: Mutability::Shared,
1968 storage_id: StorageId::of::<SparseSet<U32>>(),
1969 thread_safe: true
1970 }
1971 ],
1972 conflict: Some(Conflict::Borrow {
1973 type_info: TypeInfo {
1974 name: type_name::<SparseSet::<Usize>>().into(),
1975 mutability: Mutability::Exclusive,
1976 storage_id: StorageId::of::<SparseSet<Usize>>(),
1977 thread_safe: true
1978 },
1979 other_system: 0,
1980 other_type_info: TypeInfo {
1981 name: type_name::<SparseSet::<Usize>>().into(),
1982 mutability: Mutability::Shared,
1983 storage_id: StorageId::of::<SparseSet<Usize>>(),
1984 thread_safe: true
1985 }
1986 }),
1987 after: vec![0],
1988 after_all: vec![],
1989 before_all: vec![],
1990 unique_id: 1
1991 })
1992 );
1993
1994 let mut systems2 = info.batches_info[2].systems();
1995 assert_eq!(
1996 systems2.next(),
1997 Some(&SystemInfo {
1998 name: format!("{:?}", sys_c.as_label()),
1999 borrow: vec![TypeInfo {
2000 name: type_name::<SparseSet::<Usize>>().into(),
2001 mutability: Mutability::Shared,
2002 storage_id: StorageId::of::<SparseSet<Usize>>(),
2003 thread_safe: true
2004 },],
2005 conflict: Some(Conflict::Borrow {
2006 type_info: TypeInfo {
2007 name: type_name::<SparseSet::<Usize>>().into(),
2008 mutability: Mutability::Shared,
2009 storage_id: StorageId::of::<SparseSet<Usize>>(),
2010 thread_safe: true
2011 },
2012 other_system: 1,
2013 other_type_info: TypeInfo {
2014 name: type_name::<SparseSet::<Usize>>().into(),
2015 mutability: Mutability::Exclusive,
2016 storage_id: StorageId::of::<SparseSet<Usize>>(),
2017 thread_safe: true
2018 }
2019 }),
2020 after: vec![1],
2021 after_all: vec![],
2022 before_all: vec![],
2023 unique_id: 2
2024 })
2025 );
2026 assert_eq!(
2027 systems2.next(),
2028 Some(&SystemInfo {
2029 name: format!("{:?}", sys_d.as_label()),
2030 borrow: vec![TypeInfo {
2031 name: type_name::<SparseSet::<Usize>>().into(),
2032 mutability: Mutability::Shared,
2033 storage_id: StorageId::of::<SparseSet<Usize>>(),
2034 thread_safe: true
2035 },],
2036 conflict: Some(Conflict::Borrow {
2037 type_info: TypeInfo {
2038 name: type_name::<SparseSet::<Usize>>().into(),
2039 mutability: Mutability::Shared,
2040 storage_id: StorageId::of::<SparseSet<Usize>>(),
2041 thread_safe: true
2042 },
2043 other_system: 1,
2044 other_type_info: TypeInfo {
2045 name: type_name::<SparseSet::<Usize>>().into(),
2046 mutability: Mutability::Exclusive,
2047 storage_id: StorageId::of::<SparseSet<Usize>>(),
2048 thread_safe: true
2049 }
2050 }),
2051 after: vec![1],
2052 after_all: vec![],
2053 before_all: vec![],
2054 unique_id: 3
2055 })
2056 );
2057 }
2058}