use pi_async_rt::prelude::{AsyncRuntime, AsyncRuntimeExt};
use crate::{schedule::{MainSchedule, Schedule}, schedule_config::{IntoSystemConfigs, IntoSystemSetConfigs, ScheduleLabel, StageLabel}, world::World};
pub type App = AppInner<runtime::Runtime>;
pub struct AppInner<A: AsyncRuntime + AsyncRuntimeExt> {
pub world: World,
pub schedule: Schedule,
pub startup_schedule: Schedule,
pub rt: A,
pub is_first_run: bool,
}
impl AppInner<runtime::Runtime> {
pub fn new() -> Self {
App {
world: World::new(),
schedule: Schedule::new(true),
startup_schedule: Schedule::new(false),
rt: runtime::create_runtime(),
is_first_run: true,
}
}
}
impl<A: AsyncRuntime + AsyncRuntimeExt> AppInner<A> {
pub fn configure_set(&mut self, _stage_label: impl StageLabel, config: impl IntoSystemSetConfigs) -> &mut Self {
self.schedule.configure_set(config.into_configs());
self
}
pub fn add_system<M>(&mut self, stage_label: impl StageLabel, system: impl IntoSystemConfigs<M>) -> &mut Self {
let stage_label = stage_label.intern();
let system_config = system.into_configs();
self.schedule.add_system(stage_label, system_config);
self
}
pub fn add_startup_system<M>(&mut self, stage_label: impl StageLabel, system: impl IntoSystemConfigs<M>) -> &mut Self {
let stage_label = stage_label.intern();
let system_config = system.into_configs();
self.startup_schedule.add_system(stage_label, system_config);
self
}
pub fn run(&mut self) {
if self.is_first_run {
self.startup_schedule.run(&mut self.world, &self.rt, &MainSchedule.intern());
self.is_first_run = false;
}
self.schedule.run(&mut self.world, &self.rt, &MainSchedule.intern());
}
pub fn run_schedule(&mut self, schedule_label: impl ScheduleLabel) {
if self.is_first_run {
self.startup_schedule.run(&mut self.world, &self.rt, &MainSchedule.intern());
self.is_first_run = false;
}
self.schedule.run(&mut self.world, &self.rt, &schedule_label.intern());
}
pub async fn async_run(&mut self, schedule_label: impl ScheduleLabel) {
if self.is_first_run {
self.startup_schedule.async_run(&mut self.world, &self.rt, &MainSchedule.intern()).await;
self.is_first_run = false;
}
self.schedule.async_run(&mut self.world, &self.rt, &schedule_label.intern()).await;
}
pub async fn async_run_schedule(&mut self) {
if self.is_first_run {
self.startup_schedule.async_run(&mut self.world, &self.rt, &MainSchedule.intern()).await;
self.is_first_run = false;
}
self.schedule.async_run(&mut self.world, &self.rt, &MainSchedule.intern()).await;
}
}
#[cfg(not(any(feature="single_thread", target_arch = "wasm32")))]
mod runtime {
pub use pi_async_rt::rt::multi_thread::MultiTaskRuntime as Runtime;
use pi_async_rt::rt::multi_thread::{MultiTaskRuntimeBuilder, StealableTaskPool};
use crate::{schedule::Schedule, world::World};
pub fn create_runtime() -> Runtime {
let pool = StealableTaskPool::with(4, 100000, [1, 254], 3000);
let builer = MultiTaskRuntimeBuilder::new(pool)
.set_timer_interval(1)
.init_worker_size(4)
.set_worker_limit(4, 4);
builer.build()
}
}
#[cfg(all(feature="single_thread", not(target_arch = "wasm32")))]
mod runtime {
pub use pi_async_rt::prelude::SingleTaskRuntime as Runtime;
use pi_async_rt::prelude::{SingleTaskPool, SingleTaskRunner};
pub fn create_runtime() -> Runtime {
let pool = SingleTaskPool::default();
SingleTaskRunner::<(), SingleTaskPool<()>>::new(pool).into_local()
}
}
#[cfg(target_arch = "wasm32")]
mod runtime {
pub use pi_async_rt::rt::serial_local_compatible_wasm_runtime::LocalTaskRuntime as Runtime;
use pi_async_rt::rt::serial_local_compatible_wasm_runtime::LocalTaskRunner;
pub fn create_runtime() -> Runtime {
let runner = LocalTaskRunner::new();
runner.get_runtime()
}
}