1use crate::driver::Installer;
85use crate::system::{IntoSystem, System};
86use crate::world::{Registry, World, WorldBuilder};
87
88#[doc(hidden)]
93pub struct StageEnd;
94
95#[doc(hidden)]
100pub struct StageNode<Prev, S> {
101 prev: Prev,
102 stage: S,
103}
104
105#[doc(hidden)]
110pub trait RunSchedule: Send {
111 fn run_schedule(&mut self, world: &mut World) -> (usize, bool);
112 fn system_count(&self) -> usize;
113}
114
115impl RunSchedule for StageEnd {
116 #[inline(always)]
117 fn run_schedule(&mut self, _world: &mut World) -> (usize, bool) {
118 (0, true)
119 }
120
121 fn system_count(&self) -> usize {
122 0
123 }
124}
125
126impl<Prev: RunSchedule, S: StageRunner> RunSchedule for StageNode<Prev, S> {
127 #[inline(always)]
128 fn run_schedule(&mut self, world: &mut World) -> (usize, bool) {
129 let (prev_ran, prev_fired) = self.prev.run_schedule(world);
130 if !prev_fired {
131 return (prev_ran, false);
132 }
133 let (stage_ran, stage_fired) = self.stage.run_all(world);
134 (prev_ran + stage_ran, stage_fired)
135 }
136
137 fn system_count(&self) -> usize {
138 self.prev.system_count() + self.stage.system_count()
139 }
140}
141
142#[doc(hidden)]
147pub trait StageRunner: Send {
148 fn run_all(&mut self, world: &mut World) -> (usize, bool);
149 fn system_count(&self) -> usize;
150}
151
152macro_rules! impl_stage {
157 ($name:ident, $count:expr, $(($idx:tt, $S:ident)),+) => {
158 #[doc(hidden)]
159 pub struct $name<$($S),+>($(pub(crate) $S),+);
160
161 impl<$($S: System),+> StageRunner for $name<$($S),+> {
162 #[inline(always)]
163 fn run_all(&mut self, world: &mut World) -> (usize, bool) {
164 let mut fired = false;
165 $(fired |= self.$idx.run(world);)+
166 ($count, fired)
167 }
168
169 fn system_count(&self) -> usize {
170 $count
171 }
172 }
173 };
174}
175
176impl_stage!(Stage1, 1, (0, S0));
177impl_stage!(Stage2, 2, (0, S0), (1, S1));
178impl_stage!(Stage3, 3, (0, S0), (1, S1), (2, S2));
179impl_stage!(Stage4, 4, (0, S0), (1, S1), (2, S2), (3, S3));
180impl_stage!(Stage5, 5, (0, S0), (1, S1), (2, S2), (3, S3), (4, S4));
181impl_stage!(
182 Stage6,
183 6,
184 (0, S0),
185 (1, S1),
186 (2, S2),
187 (3, S3),
188 (4, S4),
189 (5, S5)
190);
191impl_stage!(
192 Stage7,
193 7,
194 (0, S0),
195 (1, S1),
196 (2, S2),
197 (3, S3),
198 (4, S4),
199 (5, S5),
200 (6, S6)
201);
202impl_stage!(
203 Stage8,
204 8,
205 (0, S0),
206 (1, S1),
207 (2, S2),
208 (3, S3),
209 (4, S4),
210 (5, S5),
211 (6, S6),
212 (7, S7)
213);
214
215pub trait IntoStage<Params> {
225 type Stage: StageRunner + 'static;
227 fn into_stage(self, registry: &Registry) -> Self::Stage;
229}
230
231impl<F, P, M> IntoStage<(P, M)> for F
232where
233 F: IntoSystem<P, M>,
234 F::System: 'static,
235{
236 type Stage = Stage1<F::System>;
237
238 fn into_stage(self, registry: &Registry) -> Self::Stage {
239 Stage1(self.into_system(registry))
240 }
241}
242
243macro_rules! impl_into_stage {
244 ($stage:ident, $(($F:ident, $P:ident, $M:ident, $idx:tt)),+) => {
245 impl<$($F, $P, $M),+> IntoStage<($(($P, $M),)+)> for ($($F,)+)
246 where
247 $($F: IntoSystem<$P, $M>, $F::System: 'static,)+
248 {
249 type Stage = $stage<$($F::System),+>;
250
251 fn into_stage(self, registry: &Registry) -> Self::Stage {
252 $stage($(self.$idx.into_system(registry)),+)
253 }
254 }
255 };
256}
257
258impl_into_stage!(Stage2, (F0, P0, M0, 0), (F1, P1, M1, 1));
259impl_into_stage!(Stage3, (F0, P0, M0, 0), (F1, P1, M1, 1), (F2, P2, M2, 2));
260impl_into_stage!(
261 Stage4,
262 (F0, P0, M0, 0),
263 (F1, P1, M1, 1),
264 (F2, P2, M2, 2),
265 (F3, P3, M3, 3)
266);
267impl_into_stage!(
268 Stage5,
269 (F0, P0, M0, 0),
270 (F1, P1, M1, 1),
271 (F2, P2, M2, 2),
272 (F3, P3, M3, 3),
273 (F4, P4, M4, 4)
274);
275impl_into_stage!(
276 Stage6,
277 (F0, P0, M0, 0),
278 (F1, P1, M1, 1),
279 (F2, P2, M2, 2),
280 (F3, P3, M3, 3),
281 (F4, P4, M4, 4),
282 (F5, P5, M5, 5)
283);
284impl_into_stage!(
285 Stage7,
286 (F0, P0, M0, 0),
287 (F1, P1, M1, 1),
288 (F2, P2, M2, 2),
289 (F3, P3, M3, 3),
290 (F4, P4, M4, 4),
291 (F5, P5, M5, 5),
292 (F6, P6, M6, 6)
293);
294impl_into_stage!(
295 Stage8,
296 (F0, P0, M0, 0),
297 (F1, P1, M1, 1),
298 (F2, P2, M2, 2),
299 (F3, P3, M3, 3),
300 (F4, P4, M4, 4),
301 (F5, P5, M5, 5),
302 (F6, P6, M6, 6),
303 (F7, P7, M7, 7)
304);
305
306pub struct SchedulerBuilder;
343
344impl SchedulerBuilder {
345 pub fn new() -> Self {
347 Self
348 }
349
350 pub fn root<S, Params>(self, stage: S, registry: &Registry) -> StageNode<StageEnd, S::Stage>
352 where
353 S: IntoStage<Params>,
354 {
355 StageNode {
356 prev: StageEnd,
357 stage: stage.into_stage(registry),
358 }
359 }
360}
361
362impl Default for SchedulerBuilder {
363 fn default() -> Self {
364 Self::new()
365 }
366}
367
368impl<Prev, S> StageNode<Prev, S>
373where
374 Prev: RunSchedule + 'static,
375 S: StageRunner + 'static,
376{
377 pub fn then<Next, Params>(
379 self,
380 stage: Next,
381 registry: &Registry,
382 ) -> StageNode<Self, Next::Stage>
383 where
384 Next: IntoStage<Params>,
385 {
386 StageNode {
387 prev: self,
388 stage: stage.into_stage(registry),
389 }
390 }
391}
392
393impl<Prev, S> Installer for StageNode<Prev, S>
398where
399 Self: RunSchedule + 'static,
400{
401 type Poller = SystemScheduler<Self>;
402
403 fn install(self, _world: &mut WorldBuilder) -> Self::Poller {
404 SystemScheduler { chain: self }
405 }
406}
407
408pub struct SystemScheduler<Chain> {
427 chain: Chain,
428}
429
430impl<Chain: RunSchedule> SystemScheduler<Chain> {
431 pub fn run(&mut self, world: &mut World) -> usize {
435 let (ran, _) = self.chain.run_schedule(world);
436 ran
437 }
438
439 pub fn len(&self) -> usize {
441 self.chain.system_count()
442 }
443
444 pub fn is_empty(&self) -> bool {
446 self.chain.system_count() == 0
447 }
448}
449
450#[cfg(test)]
451mod tests {
452 use super::*;
453 use crate::ResMut;
454
455 fn increment(mut val: ResMut<u64>) -> bool {
458 *val += 1;
459 true
460 }
461
462 fn set_flag(mut flag: ResMut<bool>) -> bool {
463 *flag = true;
464 true
465 }
466
467 fn false_source() -> bool {
468 false
469 }
470
471 fn should_not_run(mut val: ResMut<u64>) -> bool {
472 *val = 999;
473 true
474 }
475
476 fn source(mut val: ResMut<u64>) -> bool {
477 *val += 1;
478 *val <= 2
479 }
480
481 fn middle(mut val: ResMut<u64>) -> bool {
482 *val += 10;
483 true
484 }
485
486 fn leaf(mut val: ResMut<u64>) -> bool {
487 *val += 100;
488 true
489 }
490
491 fn double(mut val: ResMut<u64>) -> bool {
492 *val *= 2;
493 true
494 }
495
496 #[test]
499 fn single_root_always_runs() {
500 let mut builder = WorldBuilder::new();
501 builder.register::<u64>(0);
502 let reg = builder.registry();
503 let mut scheduler = builder.install_driver(SchedulerBuilder::new().root(increment, ®));
504 let mut world = builder.build();
505
506 assert_eq!(scheduler.run(&mut world), 1);
507 assert_eq!(*world.resource::<u64>(), 1);
508 }
509
510 #[test]
511 fn linear_chain_propagation() {
512 let mut builder = WorldBuilder::new();
513 builder.register::<u64>(0);
514 let reg = builder.registry();
515 let mut scheduler = builder.install_driver(
516 SchedulerBuilder::new()
517 .root(source, ®)
518 .then(middle, ®)
519 .then(leaf, ®),
520 );
521 let mut world = builder.build();
522
523 assert_eq!(scheduler.run(&mut world), 3);
524 assert_eq!(*world.resource::<u64>(), 111);
525 }
526
527 #[test]
528 fn propagation_stops_on_false() {
529 let mut builder = WorldBuilder::new();
530 builder.register::<u64>(0);
531 let reg = builder.registry();
532 let mut scheduler = builder.install_driver(
533 SchedulerBuilder::new()
534 .root(false_source, ®)
535 .then(should_not_run, ®),
536 );
537 let mut world = builder.build();
538
539 assert_eq!(scheduler.run(&mut world), 1);
540 assert_eq!(*world.resource::<u64>(), 0);
541 }
542
543 #[test]
544 fn staged_diamond() {
545 let mut builder = WorldBuilder::new();
546 builder.register::<u64>(0);
547 builder.register::<bool>(false);
548 let reg = builder.registry();
549 let mut scheduler = builder.install_driver(
550 SchedulerBuilder::new()
551 .root(increment, ®)
552 .then((increment, set_flag), ®)
553 .then(increment, ®),
554 );
555 let mut world = builder.build();
556
557 assert_eq!(scheduler.run(&mut world), 4);
558 assert!(*world.resource::<bool>());
559 assert_eq!(*world.resource::<u64>(), 3);
560 }
561
562 #[test]
563 fn multiple_roots() {
564 let mut builder = WorldBuilder::new();
565 builder.register::<u64>(0);
566 let reg = builder.registry();
567 let mut scheduler = builder
568 .install_driver(SchedulerBuilder::new().root((increment, increment, increment), ®));
569 let mut world = builder.build();
570
571 assert_eq!(scheduler.run(&mut world), 3);
572 assert_eq!(*world.resource::<u64>(), 3);
573 }
574
575 #[test]
576 fn scheduler_does_not_bump_sequence() {
577 let mut builder = WorldBuilder::new();
578 builder.register::<u64>(0);
579 let reg = builder.registry();
580 let mut scheduler = builder.install_driver(SchedulerBuilder::new().root(increment, ®));
581 let mut world = builder.build();
582
583 let before = world.current_sequence();
584 scheduler.run(&mut world);
585 assert_eq!(world.current_sequence(), before);
586 }
587
588 #[test]
589 fn mutations_visible_downstream() {
590 let mut builder = WorldBuilder::new();
591 builder.register::<u64>(1);
592 let reg = builder.registry();
593 let mut scheduler = builder.install_driver(
594 SchedulerBuilder::new()
595 .root(double, ®)
596 .then(double, ®),
597 );
598 let mut world = builder.build();
599
600 scheduler.run(&mut world);
601 assert_eq!(*world.resource::<u64>(), 4);
602 }
603
604 #[test]
607 fn multi_system_stage_all_run() {
608 let mut builder = WorldBuilder::new();
609 builder.register::<u64>(0);
610 builder.register::<bool>(false);
611 let reg = builder.registry();
612 let mut scheduler = builder
613 .install_driver(SchedulerBuilder::new().root((increment, increment, set_flag), ®));
614 let mut world = builder.build();
615
616 assert_eq!(scheduler.run(&mut world), 3);
617 assert_eq!(*world.resource::<u64>(), 2);
618 assert!(*world.resource::<bool>());
619 }
620
621 #[test]
622 fn stage_propagation_any_semantics() {
623 fn false_increment(mut val: ResMut<u64>) -> bool {
624 *val += 1;
625 false
626 }
627
628 let mut builder = WorldBuilder::new();
629 builder.register::<u64>(0);
630 let reg = builder.registry();
631 let mut scheduler = builder.install_driver(
632 SchedulerBuilder::new()
633 .root((false_increment, increment), ®)
634 .then(increment, ®),
635 );
636 let mut world = builder.build();
637
638 assert_eq!(scheduler.run(&mut world), 3);
639 assert_eq!(*world.resource::<u64>(), 3);
640 }
641
642 #[test]
643 fn stage_propagation_all_false_stops() {
644 fn false_increment(mut val: ResMut<u64>) -> bool {
645 *val += 1;
646 false
647 }
648
649 let mut builder = WorldBuilder::new();
650 builder.register::<u64>(0);
651 let reg = builder.registry();
652 let mut scheduler = builder.install_driver(
653 SchedulerBuilder::new()
654 .root((false_increment, false_increment), ®)
655 .then(should_not_run, ®),
656 );
657 let mut world = builder.build();
658
659 assert_eq!(scheduler.run(&mut world), 2);
660 assert_eq!(*world.resource::<u64>(), 2);
661 }
662
663 #[test]
664 fn void_systems_in_stage() {
665 fn void_increment(mut val: ResMut<u64>) {
666 *val += 1;
667 }
668
669 let mut builder = WorldBuilder::new();
670 builder.register::<u64>(0);
671 let reg = builder.registry();
672 let mut scheduler = builder.install_driver(
673 SchedulerBuilder::new()
674 .root(void_increment, ®)
675 .then(increment, ®),
676 );
677 let mut world = builder.build();
678
679 assert_eq!(scheduler.run(&mut world), 2);
680 assert_eq!(*world.resource::<u64>(), 2);
681 }
682
683 #[test]
684 fn mixed_bool_void_stage() {
685 fn void_increment(mut val: ResMut<u64>) {
686 *val += 1;
687 }
688
689 fn false_increment(mut val: ResMut<u64>) -> bool {
690 *val += 1;
691 false
692 }
693
694 let mut builder = WorldBuilder::new();
695 builder.register::<u64>(0);
696 let reg = builder.registry();
697 let mut scheduler = builder.install_driver(
698 SchedulerBuilder::new()
699 .root((false_increment, void_increment), ®)
700 .then(increment, ®),
701 );
702 let mut world = builder.build();
703
704 assert_eq!(scheduler.run(&mut world), 3);
705 assert_eq!(*world.resource::<u64>(), 3);
706 }
707
708 #[test]
709 fn scheduler_chain_is_send() {
710 fn assert_send<T: Send>(_: &T) {}
711
712 let mut builder = WorldBuilder::new();
713 builder.register::<u64>(0);
714 builder.register::<bool>(false);
715 let reg = builder.registry();
716 let scheduler = builder.install_driver(
717 SchedulerBuilder::new()
718 .root(increment, ®)
719 .then((increment, set_flag), ®)
720 .then(double, ®),
721 );
722 assert_send(&scheduler);
723 }
724
725 #[test]
726 fn three_stage_linear() {
727 let mut builder = WorldBuilder::new();
728 builder.register::<u64>(0);
729 builder.register::<bool>(false);
730 let reg = builder.registry();
731 let mut scheduler = builder.install_driver(
732 SchedulerBuilder::new()
733 .root(increment, ®)
734 .then((increment, set_flag), ®)
735 .then(double, ®),
736 );
737 let mut world = builder.build();
738
739 assert_eq!(scheduler.run(&mut world), 4);
740 assert!(*world.resource::<bool>());
741 assert_eq!(*world.resource::<u64>(), 4);
743 }
744}