1mod builder;
2mod run_batches;
3
4pub use builder::WorldBuilder;
5
6use crate::all_storages::{AllStorages, CustomStorageAccess, TupleDeleteAny, TupleRetainStorage};
7use crate::atomic_refcell::{ARef, ARefMut, AtomicRefCell};
8use crate::borrow::WorldBorrow;
9use crate::component::{Component, Unique};
10use crate::entities::Entities;
11use crate::entity_id::EntityId;
12use crate::error;
13use crate::get_component::GetComponent;
14use crate::get_unique::GetUnique;
15use crate::info::WorkloadsInfo;
16use crate::iter_component::{IntoIterRef, IterComponent};
17use crate::memory_usage::WorldMemoryUsage;
18use crate::r#mut::Mut;
19use crate::reserve::BulkEntityIter;
20use crate::scheduler::Label;
21use crate::scheduler::{AsLabel, Batches, Scheduler};
22use crate::sparse_set::{BulkAddEntity, TupleAddComponent, TupleDelete, TupleRemove};
23use crate::storage::{Storage, StorageId};
24use crate::system::System;
25use crate::tracking::{TrackingTimestamp, TupleTrack};
26use crate::views::EntitiesViewMut;
27use alloc::boxed::Box;
28use alloc::format;
29use alloc::sync::Arc;
30use core::sync::atomic::AtomicU32;
31
32pub struct World {
34 pub(crate) all_storages: AtomicRefCell<AllStorages>,
35 pub(crate) scheduler: AtomicRefCell<Scheduler>,
36 counter: Arc<AtomicU32>,
37 #[cfg(feature = "parallel")]
38 thread_pool: Option<rayon::ThreadPool>,
39}
40
41#[cfg(feature = "std")]
42impl Default for World {
43 fn default() -> Self {
45 let counter = Arc::new(AtomicU32::new(1));
46 World {
47 #[cfg(not(feature = "thread_local"))]
48 all_storages: AtomicRefCell::new(AllStorages::new(counter.clone())),
49 #[cfg(feature = "thread_local")]
50 all_storages: AtomicRefCell::new_non_send(
51 AllStorages::new(counter.clone()),
52 Arc::new(crate::std_thread_id_generator),
53 ),
54 scheduler: AtomicRefCell::new(Default::default()),
55 counter,
56 #[cfg(feature = "parallel")]
57 thread_pool: None,
58 }
59 }
60}
61
62impl World {
63 #[cfg(feature = "std")]
65 pub fn new() -> World {
66 Default::default()
67 }
68 #[cfg(feature = "parallel")]
70 pub fn remove_local_thread_pool(&mut self) -> Option<rayon::ThreadPool> {
71 self.thread_pool.take()
72 }
73 #[track_caller]
104 pub fn add_unique<T: Send + Sync + Unique>(&self, component: T) {
105 self.all_storages.borrow().unwrap().add_unique(component);
106 }
107 #[cfg(feature = "thread_local")]
141 #[cfg_attr(docsrs, doc(cfg(feature = "thread_local")))]
142 #[track_caller]
143 pub fn add_unique_non_send<T: Sync + Unique>(&self, component: T) {
144 self.all_storages
145 .borrow()
146 .unwrap()
147 .add_unique_non_send(component);
148 }
149 #[cfg(feature = "thread_local")]
183 #[cfg_attr(docsrs, doc(cfg(feature = "thread_local")))]
184 #[track_caller]
185 pub fn add_unique_non_sync<T: Send + Unique>(&self, component: T) {
186 self.all_storages
187 .borrow()
188 .unwrap()
189 .add_unique_non_sync(component);
190 }
191 #[cfg(feature = "thread_local")]
225 #[cfg_attr(docsrs, doc(cfg(feature = "thread_local")))]
226 #[track_caller]
227 pub fn add_unique_non_send_sync<T: Unique>(&self, component: T) {
228 self.all_storages
229 .borrow()
230 .unwrap()
231 .add_unique_non_send_sync(component);
232 }
233 pub fn remove_unique<T: Unique>(&self) -> Result<T, error::UniqueRemove> {
264 self.all_storages
265 .borrow()
266 .map_err(|_| error::UniqueRemove::AllStorages)?
267 .remove_unique::<T>()
268 }
269 #[doc = "Borrows the requested storages, if they don't exist they'll get created.
270You can use a tuple to get multiple storages at once.
271
272You can use:
273* [View]\\<T\\> for a shared access to `T` storage
274* [ViewMut]\\<T\\> for an exclusive access to `T` storage
275* [EntitiesView] for a shared access to the entity storage
276* [EntitiesViewMut] for an exclusive reference to the entity storage
277* [AllStoragesViewMut] for an exclusive access to the storage of all components, ⚠️ can't coexist with any other storage borrow
278* [UniqueView]\\<T\\> for a shared access to a `T` unique storage
279* [UniqueViewMut]\\<T\\> for an exclusive access to a `T` unique storage
280* `Option<V>` with one or multiple views for fallible access to one or more storages"]
281 #[cfg_attr(
282 all(feature = "thread_local", docsrs),
283 doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
284 )]
285 #[cfg_attr(
286 all(feature = "thread_local", docsrs),
287 doc = " * [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
288 * [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
289[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
290 )]
291 #[cfg_attr(
292 all(feature = "thread_local", not(docsrs)),
293 doc = "* [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
294* [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
295[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
296 )]
297 #[cfg_attr(
298 not(feature = "thread_local"),
299 doc = "* NonSend: must activate the *thread_local* feature"
300 )]
301 #[cfg_attr(
302 all(feature = "thread_local", docsrs),
303 doc = " * [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
304 * [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
305[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
306 )]
307 #[cfg_attr(
308 all(feature = "thread_local", not(docsrs)),
309 doc = "* [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
310* [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
311[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
312 )]
313 #[cfg_attr(
314 not(feature = "thread_local"),
315 doc = "* NonSync: must activate the *thread_local* feature"
316 )]
317 #[cfg_attr(
318 all(feature = "thread_local", docsrs),
319 doc = " * [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
320 * [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
321[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
322 )]
323 #[cfg_attr(
324 all(feature = "thread_local", not(docsrs)),
325 doc = "* [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
326* [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
327[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
328 )]
329 #[cfg_attr(
330 not(feature = "thread_local"),
331 doc = "* NonSendSync: must activate the *thread_local* feature"
332 )]
333 #[doc = "
334### Borrows
335
336- [AllStorages] (exclusive) when requesting [AllStoragesViewMut]
337- [AllStorages] (shared) + storage (exclusive or shared) for all other views
338
339### Errors
340
341- [AllStorages] borrow failed.
342- Storage borrow failed.
343- Unique storage did not exist.
344
345### Example
346```
347use shipyard::{Component, EntitiesView, View, ViewMut, World};
348
349#[derive(Component)]
350struct U32(u32);
351
352#[derive(Component)]
353struct USIZE(usize);
354
355let world = World::new();
356
357let u32s = world.borrow::<View<U32>>().unwrap();
358let (entities, mut usizes) = world
359 .borrow::<(EntitiesView, ViewMut<USIZE>)>()
360 .unwrap();
361```
362[AllStorages]: crate::AllStorages
363[EntitiesView]: crate::Entities
364[EntitiesViewMut]: crate::Entities
365[AllStoragesViewMut]: crate::AllStorages
366[World]: crate::World
367[View]: crate::View
368[ViewMut]: crate::ViewMut
369[UniqueView]: crate::UniqueView
370[UniqueViewMut]: crate::UniqueViewMut"]
371 #[cfg_attr(feature = "thread_local", doc = "[NonSend]: crate::NonSend")]
372 #[cfg_attr(feature = "thread_local", doc = "[NonSync]: crate::NonSync")]
373 #[cfg_attr(feature = "thread_local", doc = "[NonSendSync]: crate::NonSendSync")]
374 pub fn borrow<V: WorldBorrow>(&self) -> Result<V::WorldView<'_>, error::GetStorage> {
375 let current = self.get_current();
376
377 V::world_borrow(self, None, current)
378 }
379 #[doc = "Borrows the requested storages, runs the function and evaluates to the function's return value.
380Data can be passed to the function, this always has to be a single type but you can use a tuple if needed.
381
382You can use:
383* [View]\\<T\\> for a shared access to `T` storage
384* [ViewMut]\\<T\\> for an exclusive access to `T` storage
385* [EntitiesView] for a shared access to the entity storage
386* [EntitiesViewMut] for an exclusive reference to the entity storage
387* [AllStoragesViewMut] for an exclusive access to the storage of all components, ⚠️ can't coexist with any other storage borrow
388* [UniqueView]\\<T\\> for a shared access to a `T` unique storage
389* [UniqueViewMut]\\<T\\> for an exclusive access to a `T` unique storage
390* `Option<V>` with one or multiple views for fallible access to one or more storages"]
391 #[cfg_attr(
392 all(feature = "thread_local", docsrs),
393 doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
394 )]
395 #[cfg_attr(
396 all(feature = "thread_local", docsrs),
397 doc = " * [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
398 * [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
399[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
400 )]
401 #[cfg_attr(
402 all(feature = "thread_local", not(docsrs)),
403 doc = "* [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
404* [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
405[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
406 )]
407 #[cfg_attr(
408 not(feature = "thread_local"),
409 doc = "* NonSend: must activate the *thread_local* feature"
410 )]
411 #[cfg_attr(
412 all(feature = "thread_local", docsrs),
413 doc = " * [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
414 * [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
415[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
416 )]
417 #[cfg_attr(
418 all(feature = "thread_local", not(docsrs)),
419 doc = "* [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
420* [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
421[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
422 )]
423 #[cfg_attr(
424 not(feature = "thread_local"),
425 doc = "* NonSync: must activate the *thread_local* feature"
426 )]
427 #[cfg_attr(
428 all(feature = "thread_local", docsrs),
429 doc = " * [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
430 * [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
431[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
432 )]
433 #[cfg_attr(
434 all(feature = "thread_local", not(docsrs)),
435 doc = "* [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
436* [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
437[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
438 )]
439 #[cfg_attr(
440 not(feature = "thread_local"),
441 doc = "* NonSendSync: must activate the *thread_local* feature"
442 )]
443 #[doc = "
444### Borrows
445
446- [AllStorages] (exclusive) when requesting [AllStoragesViewMut]
447- [AllStorages] (shared) + storage (exclusive or shared) for all other views
448
449### Panics
450
451- [AllStorages] borrow failed.
452- Storage borrow failed.
453- Unique storage did not exist.
454- Error returned by user.
455
456### Example
457```
458use shipyard::{Component, EntityId, Get, ViewMut, World};
459
460#[derive(Component)]
461struct Position([f32; 2]);
462
463fn sys1((entity, [x, y]): (EntityId, [f32; 2]), mut positions: ViewMut<Position>) {
464 if let Ok(mut pos) = (&mut positions).get(entity) {
465 pos.0 = [x, y];
466 }
467}
468
469let world = World::new();
470
471world.run_with_data(sys1, (EntityId::dead(), [0., 0.]));
472```
473[AllStorages]: crate::AllStorages
474[EntitiesView]: crate::Entities
475[EntitiesViewMut]: crate::Entities
476[AllStoragesViewMut]: crate::AllStorages
477[World]: crate::World
478[View]: crate::View
479[ViewMut]: crate::ViewMut
480[UniqueView]: crate::UniqueView
481[UniqueViewMut]: crate::UniqueViewMut"]
482 #[cfg_attr(feature = "thread_local", doc = "[NonSend]: crate::NonSend")]
483 #[cfg_attr(feature = "thread_local", doc = "[NonSync]: crate::NonSync")]
484 #[cfg_attr(feature = "thread_local", doc = "[NonSendSync]: crate::NonSendSync")]
485 #[track_caller]
486 pub fn run_with_data<Data, B, S: System<(Data,), B>>(
487 &self,
488 system: S,
489 data: Data,
490 ) -> S::Return {
491 #[cfg(feature = "tracing")]
492 let system_span = tracing::info_span!("system", name = ?core::any::type_name::<S>());
493 #[cfg(feature = "tracing")]
494 let _system_span = system_span.enter();
495
496 system
497 .run((data,), self)
498 .map_err(error::Run::GetStorage)
499 .unwrap()
500 }
501 #[doc = "Borrows the requested storages, runs the function and evaluates to the function's return value.
502
503You can use:
504* [View]\\<T\\> for a shared access to `T` storage
505* [ViewMut]\\<T\\> for an exclusive access to `T` storage
506* [EntitiesView] for a shared access to the entity storage
507* [EntitiesViewMut] for an exclusive reference to the entity storage
508* [AllStoragesViewMut] for an exclusive access to the storage of all components, ⚠️ can't coexist with any other storage borrow
509* [UniqueView]\\<T\\> for a shared access to a `T` unique storage
510* [UniqueViewMut]\\<T\\> for an exclusive access to a `T` unique storage
511* `Option<V>` with one or multiple views for fallible access to one or more storages"]
512 #[cfg_attr(
513 all(feature = "thread_local", docsrs),
514 doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
515 )]
516 #[cfg_attr(
517 all(feature = "thread_local", docsrs),
518 doc = " * [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
519 * [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
520[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
521 )]
522 #[cfg_attr(
523 all(feature = "thread_local", not(docsrs)),
524 doc = "* [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
525* [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
526[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
527 )]
528 #[cfg_attr(
529 not(feature = "thread_local"),
530 doc = "* NonSend: must activate the *thread_local* feature"
531 )]
532 #[cfg_attr(
533 all(feature = "thread_local", docsrs),
534 doc = " * [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
535 * [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
536[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
537 )]
538 #[cfg_attr(
539 all(feature = "thread_local", not(docsrs)),
540 doc = "* [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
541* [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
542[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
543 )]
544 #[cfg_attr(
545 not(feature = "thread_local"),
546 doc = "* NonSync: must activate the *thread_local* feature"
547 )]
548 #[cfg_attr(
549 all(feature = "thread_local", docsrs),
550 doc = " * [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
551 * [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
552[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
553 )]
554 #[cfg_attr(
555 all(feature = "thread_local", not(docsrs)),
556 doc = "* [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
557* [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
558[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
559 )]
560 #[cfg_attr(
561 not(feature = "thread_local"),
562 doc = "* NonSendSync: must activate the *thread_local* feature"
563 )]
564 #[doc = "
565### Borrows
566
567- [AllStorages] (exclusive) when requesting [AllStoragesViewMut]
568- [AllStorages] (shared) + storage (exclusive or shared) for all other views
569
570### Panics
571
572- [AllStorages] borrow failed.
573- Storage borrow failed.
574- Unique storage did not exist.
575- Error returned by user.
576
577### Example
578```
579use shipyard::{Component, View, ViewMut, World};
580
581#[derive(Component)]
582struct I32(i32);
583
584#[derive(Component)]
585struct USIZE(usize);
586
587#[derive(Component)]
588struct U32(u32);
589
590fn sys1(i32s: View<I32>) -> i32 {
591 0
592}
593
594let world = World::new();
595
596world
597 .run(|usizes: View<USIZE>, mut u32s: ViewMut<U32>| {
598 // -- snip --
599 });
600
601let i = world.run(sys1);
602```
603[AllStorages]: crate::AllStorages
604[EntitiesView]: crate::Entities
605[EntitiesViewMut]: crate::Entities
606[AllStoragesViewMut]: crate::AllStorages
607[World]: crate::World
608[View]: crate::View
609[ViewMut]: crate::ViewMut
610[UniqueView]: crate::UniqueView
611[UniqueViewMut]: crate::UniqueViewMut"]
612 #[cfg_attr(feature = "thread_local", doc = "[NonSend]: crate::NonSend")]
613 #[cfg_attr(feature = "thread_local", doc = "[NonSync]: crate::NonSync")]
614 #[cfg_attr(feature = "thread_local", doc = "[NonSendSync]: crate::NonSendSync")]
615 #[track_caller]
616 pub fn run<B, S: System<(), B>>(&self, system: S) -> S::Return {
617 #[cfg(feature = "tracing")]
618 let system_span = tracing::info_span!("system", name = ?core::any::type_name::<S>());
619 #[cfg(feature = "tracing")]
620 let _system_span = system_span.enter();
621
622 system
623 .run((), self)
624 .map_err(error::Run::GetStorage)
625 .unwrap()
626 }
627 pub fn set_default_workload<T>(
638 &self,
639 name: impl AsLabel<T>,
640 ) -> Result<(), error::SetDefaultWorkload> {
641 self.scheduler
642 .borrow_mut()
643 .map_err(|_| error::SetDefaultWorkload::Borrow)?
644 .set_default(name.as_label())
645 }
646 #[track_caller]
656 pub fn rename_workload<T, U>(&self, old_name: impl AsLabel<T>, new_name: impl AsLabel<U>) {
657 let old_label = old_name.as_label();
658 let new_label = new_name.as_label();
659
660 self.scheduler
661 .borrow_mut()
662 .unwrap()
663 .rename(&old_label, Box::new(new_label));
664 }
665 pub fn run_workload<T>(&self, label: impl AsLabel<T>) -> Result<(), error::RunWorkload> {
679 let scheduler = self
680 .scheduler
681 .borrow()
682 .map_err(|_| error::RunWorkload::Scheduler)?;
683
684 let label = label.as_label();
685 let batches = scheduler.workload(&*label)?;
686
687 self.run_batches(
688 &scheduler.systems,
689 &scheduler.system_names,
690 batches,
691 &*label,
692 )
693 }
694 #[track_caller]
716 pub fn contains_workload<T>(&self, name: impl AsLabel<T>) -> bool {
717 let label = name.as_label();
718
719 self.scheduler.borrow().unwrap().contains_workload(&*label)
720 }
721 #[allow(clippy::type_complexity)]
722 pub(crate) fn run_batches(
723 &self,
724 systems: &[Box<dyn Fn(&World) -> Result<(), error::Run> + Send + Sync + 'static>],
725 system_names: &[Box<dyn Label>],
726 batches: &Batches,
727 workload_name: &dyn Label,
728 ) -> Result<(), error::RunWorkload> {
729 if let Some(run_if) = &batches.run_if {
730 if !run_if
731 .run(self)
732 .map_err(|err| error::RunWorkload::Run((workload_name.dyn_clone(), err)))?
733 {
734 return Ok(());
735 }
736 }
737
738 #[cfg(feature = "parallel")]
739 {
740 self.run_batches_parallel(systems, system_names, batches, workload_name)
741 }
742
743 #[cfg(not(feature = "parallel"))]
744 {
745 self.run_batches_sequential(systems, system_names, batches, workload_name)
746 }
747 }
748 pub fn run_default_workload(&self) -> Result<(), error::RunWorkload> {
761 let scheduler = self
762 .scheduler
763 .borrow()
764 .map_err(|_| error::RunWorkload::Scheduler)?;
765
766 if !scheduler.is_empty() {
767 self.run_batches(
768 &scheduler.systems,
769 &scheduler.system_names,
770 scheduler.default_workload(),
771 &scheduler.default,
772 )?
773 }
774 Ok(())
775 }
776 pub fn all_storages(&self) -> Result<ARef<'_, &'_ AllStorages>, error::Borrow> {
783 self.all_storages.borrow()
784 }
785 pub fn all_storages_mut(&self) -> Result<ARefMut<'_, &'_ mut AllStorages>, error::Borrow> {
792 self.all_storages.borrow_mut()
793 }
794 pub fn add_custom_storage<S: 'static + Storage + Send + Sync>(
800 &self,
801 storage_id: StorageId,
802 storage: S,
803 ) -> Result<(), error::Borrow> {
804 let _ = self
805 .all_storages
806 .borrow()?
807 .custom_storage_or_insert_by_id(storage_id, || storage);
808
809 Ok(())
810 }
811
812 #[inline]
814 pub(crate) fn get_current(&self) -> TrackingTimestamp {
815 TrackingTimestamp::new(
816 self.counter
817 .fetch_add(1, core::sync::atomic::Ordering::Acquire),
818 )
819 }
820
821 pub fn get_tracking_timestamp(&self) -> TrackingTimestamp {
823 TrackingTimestamp::new(self.counter.load(core::sync::atomic::Ordering::Acquire))
824 }
825}
826
827impl World {
828 #[inline]
848 pub fn add_entity<C: TupleAddComponent>(&mut self, component: C) -> EntityId {
849 self.all_storages.get_mut().add_entity(component)
850 }
851 #[inline]
870 pub fn bulk_add_entity<T: BulkAddEntity>(&mut self, source: T) -> BulkEntityIter<'_> {
871 self.all_storages.get_mut().bulk_add_entity(source)
872 }
873 #[track_caller]
902 #[inline]
903 pub fn add_component<C: TupleAddComponent>(&mut self, entity: EntityId, component: C) {
904 self.all_storages.get_mut().add_component(entity, component)
905 }
906 #[inline]
927 pub fn delete_component<C: TupleDelete>(&mut self, entity: EntityId) {
928 self.all_storages.get_mut().delete_component::<C>(entity)
929 }
930 #[inline]
952 pub fn remove<C: TupleRemove>(&mut self, entity: EntityId) -> C::Out {
953 self.all_storages.get_mut().remove::<C>(entity)
954 }
955 #[inline]
975 pub fn delete_entity(&mut self, entity: EntityId) -> bool {
976 self.all_storages.get_mut().delete_entity(entity)
977 }
978 #[inline]
998 pub fn strip(&mut self, entity: EntityId) {
999 self.all_storages.get_mut().strip(entity);
1000 }
1001 #[inline]
1031 pub fn delete_any<S: TupleDeleteAny>(&mut self) {
1032 self.all_storages.get_mut().delete_any::<S>();
1033 }
1034 #[inline]
1056 pub fn retain_storage<S: TupleRetainStorage>(&mut self, entity: EntityId) {
1057 self.all_storages.get_mut().retain_storage::<S>(entity);
1058 }
1059 #[inline]
1062 pub fn retain_storage_by_id(&mut self, entity: EntityId, excluded_storage: &[StorageId]) {
1063 self.all_storages
1064 .get_mut()
1065 .retain_storage_by_id(entity, excluded_storage);
1066 }
1067 #[inline]
1079 pub fn clear(&mut self) {
1080 self.all_storages.get_mut().clear();
1081 }
1082 pub fn clear_all_removed_and_deleted(&mut self) {
1084 self.all_storages.get_mut().clear_all_removed_and_deleted()
1085 }
1086 pub fn clear_all_removed_and_deleted_older_than_timestamp(
1088 &mut self,
1089 timestamp: TrackingTimestamp,
1090 ) {
1091 self.all_storages
1092 .get_mut()
1093 .clear_all_removed_and_deleted_older_than_timestamp(timestamp)
1094 }
1095 #[inline]
1099 pub fn spawn(&mut self, entity: EntityId) -> bool {
1100 self.all_storages.get_mut().spawn(entity)
1101 }
1102
1103 pub fn retain<T: Component + Send + Sync>(&mut self, f: impl FnMut(EntityId, &T) -> bool) {
1109 self.all_storages.get_mut().retain(f);
1110 }
1111
1112 pub fn retain_mut<T: Component + Send + Sync>(
1118 &mut self,
1119 f: impl FnMut(EntityId, Mut<'_, T>) -> bool,
1120 ) {
1121 self.all_storages.get_mut().retain_mut(f);
1122 }
1123
1124 pub fn memory_usage(&self) -> WorldMemoryUsage<'_> {
1126 WorldMemoryUsage(self)
1127 }
1128 #[track_caller]
1138 pub fn workloads_info(&self) -> WorkloadsInfo {
1139 let scheduler = self.scheduler.borrow().unwrap();
1140
1141 WorkloadsInfo(
1142 scheduler
1143 .workloads_info
1144 .iter()
1145 .map(|(name, workload_info)| (format!("{:?}", name), workload_info.clone()))
1146 .collect(),
1147 )
1148 }
1149
1150 pub fn track_insertion<T: TupleTrack>(&mut self) -> &mut World {
1152 self.all_storages.get_mut().track_insertion::<T>();
1153 self
1154 }
1155
1156 pub fn track_modification<T: TupleTrack>(&mut self) -> &mut World {
1158 self.all_storages.get_mut().track_modification::<T>();
1159 self
1160 }
1161
1162 pub fn track_deletion<T: TupleTrack>(&mut self) -> &mut World {
1164 self.all_storages.get_mut().track_deletion::<T>();
1165 self
1166 }
1167
1168 pub fn track_removal<T: TupleTrack>(&mut self) -> &mut World {
1170 self.all_storages.get_mut().track_removal::<T>();
1171 self
1172 }
1173
1174 pub fn track_all<T: TupleTrack>(&mut self) {
1176 self.all_storages.get_mut().track_all::<T>();
1177 }
1178
1179 #[doc = "Retrieve components of `entity`.
1180
1181Multiple components can be queried at the same time using a tuple.
1182
1183You can use:
1184* `&T` for a shared access to `T` component
1185* `&mut T` for an exclusive access to `T` component"]
1186 #[cfg_attr(
1187 all(feature = "thread_local", docsrs),
1188 doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
1189 )]
1190 #[cfg_attr(
1191 all(feature = "thread_local"),
1192 doc = "* [NonSend]<&T> for a shared access to a `T` component where `T` isn't `Send`
1193* [NonSend]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send`
1194* [NonSync]<&T> for a shared access to a `T` component where `T` isn't `Sync`
1195* [NonSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Sync`
1196* [NonSendSync]<&T> for a shared access to a `T` component where `T` isn't `Send` nor `Sync`
1197* [NonSendSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send` nor `Sync`"
1198 )]
1199 #[cfg_attr(
1200 not(feature = "thread_local"),
1201 doc = "* NonSend: must activate the *thread_local* feature
1202* NonSync: must activate the *thread_local* feature
1203* NonSendSync: must activate the *thread_local* feature"
1204 )]
1205 #[doc = "
1206### Borrows
1207
1208- [AllStorages] (shared) + storage (exclusive or shared)
1209
1210### Errors
1211
1212- [AllStorages] borrow failed.
1213- Storage borrow failed.
1214- Entity does not have the component.
1215
1216### Example
1217```
1218use shipyard::{Component, World};
1219
1220#[derive(Component, Debug, PartialEq, Eq)]
1221struct U32(u32);
1222
1223#[derive(Component, Debug, PartialEq, Eq)]
1224struct USIZE(usize);
1225
1226let mut world = World::new();
1227
1228let entity = world.add_entity((USIZE(0), U32(1)));
1229
1230let (i, j) = world.get::<(&USIZE, &mut U32)>(entity).unwrap();
1231
1232assert!(*i == &USIZE(0));
1233assert!(*j == &U32(1));
1234```"]
1235 #[cfg_attr(
1236 feature = "thread_local",
1237 doc = "[NonSend]: crate::NonSend
1238[NonSync]: crate::NonSync
1239[NonSendSync]: crate::NonSendSync"
1240 )]
1241 #[inline]
1242 pub fn get<T: GetComponent>(
1243 &self,
1244 entity: EntityId,
1245 ) -> Result<T::Out<'_>, error::GetComponent> {
1246 let (all_storages, all_borrow) = unsafe {
1247 ARef::destructure(
1248 self.all_storages
1249 .borrow()
1250 .map_err(error::GetStorage::AllStoragesBorrow)?,
1251 )
1252 };
1253
1254 let current = self.get_current();
1255
1256 T::get(all_storages, Some(all_borrow), current, entity)
1257 }
1258
1259 #[doc = "Retrieve a unique component.
1260
1261You can use:
1262* `&T` for a shared access to `T` unique component
1263* `&mut T` for an exclusive access to `T` unique component"]
1264 #[cfg_attr(
1265 all(feature = "thread_local", docsrs),
1266 doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
1267 )]
1268 #[cfg_attr(
1269 all(feature = "thread_local"),
1270 doc = "* [NonSend]<&T> for a shared access to a `T` unique component where `T` isn't `Send`
1271* [NonSend]<&mut T> for an exclusive access to a `T` unique component where `T` isn't `Send`
1272* [NonSync]<&T> for a shared access to a `T` unique component where `T` isn't `Sync`
1273* [NonSync]<&mut T> for an exclusive access to a `T` unique component where `T` isn't `Sync`
1274* [NonSendSync]<&T> for a shared access to a `T` unique component where `T` isn't `Send` nor `Sync`
1275* [NonSendSync]<&mut T> for an exclusive access to a `T` unique component where `T` isn't `Send` nor `Sync`"
1276 )]
1277 #[cfg_attr(
1278 not(feature = "thread_local"),
1279 doc = "* NonSend: must activate the *thread_local* feature
1280* NonSync: must activate the *thread_local* feature
1281* NonSendSync: must activate the *thread_local* feature"
1282 )]
1283 #[doc = "
1284### Borrows
1285
1286- [AllStorages] (shared) + storage (exclusive or shared)
1287
1288### Errors
1289
1290- [AllStorages] borrow failed.
1291- Storage borrow failed.
1292
1293### Example
1294```
1295use shipyard::{Unique, World};
1296
1297#[derive(Unique, Debug, PartialEq, Eq)]
1298struct U32(u32);
1299
1300let mut world = World::new();
1301
1302world.add_unique(U32(0));
1303
1304let i = world.get_unique::<&U32>().unwrap();
1305
1306assert!(*i == U32(0));
1307```"]
1308 #[cfg_attr(
1309 feature = "thread_local",
1310 doc = "[NonSend]: crate::NonSend
1311[NonSync]: crate::NonSync
1312[NonSendSync]: crate::NonSendSync"
1313 )]
1314 #[inline]
1315 pub fn get_unique<T: GetUnique>(&self) -> Result<T::Out<'_>, error::GetStorage> {
1316 let (all_storages, all_borrow) = unsafe {
1317 ARef::destructure(
1318 self.all_storages
1319 .borrow()
1320 .map_err(error::GetStorage::AllStoragesBorrow)?,
1321 )
1322 };
1323
1324 T::get_unique(all_storages, Some(all_borrow))
1325 }
1326
1327 #[doc = "Iterate components.
1328
1329Multiple components can be iterated at the same time using a tuple.
1330
1331You can use:
1332* `&T` for a shared access to `T` component
1333* `&mut T` for an exclusive access to `T` component"]
1334 #[cfg_attr(
1335 all(feature = "thread_local", docsrs),
1336 doc = "* <span style=\"display: table;color: #2f2f2f;background-color: #C4ECFF;border-width: 1px;border-style: solid;border-color: #7BA5DB;padding: 3px;margin-bottom: 5px; font-size: 90%\">This is supported on <strong><code style=\"background-color: #C4ECFF\">feature=\"thread_local\"</code></strong> only:</span>"
1337 )]
1338 #[cfg_attr(
1339 all(feature = "thread_local"),
1340 doc = "* [NonSend]<&T> for a shared access to a `T` component where `T` isn't `Send`
1341* [NonSend]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send`
1342* [NonSync]<&T> for a shared access to a `T` component where `T` isn't `Sync`
1343* [NonSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Sync`
1344* [NonSendSync]<&T> for a shared access to a `T` component where `T` isn't `Send` nor `Sync`
1345* [NonSendSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send` nor `Sync`"
1346 )]
1347 #[cfg_attr(
1348 not(feature = "thread_local"),
1349 doc = "* NonSend: must activate the *thread_local* feature
1350* NonSync: must activate the *thread_local* feature
1351* NonSendSync: must activate the *thread_local* feature"
1352 )]
1353 #[doc = "
1354### Borrows
1355
1356- [AllStorages] (shared)
1357
1358### Panics
1359
1360- [AllStorages] borrow failed.
1361
1362### Example
1363```
1364use shipyard::{Component, World};
1365
1366#[derive(Component, Debug, PartialEq, Eq)]
1367struct U32(u32);
1368
1369#[derive(Component, Debug, PartialEq, Eq)]
1370struct USIZE(usize);
1371
1372let mut world = World::new();
1373
1374let entity = world.add_entity((USIZE(0), U32(1)));
1375
1376let mut iter = world.iter::<(&USIZE, &mut U32)>();
1377
1378for (i, j) in &mut iter {
1379 // <-- SNIP -->
1380}
1381```"]
1382 #[cfg_attr(
1383 feature = "thread_local",
1384 doc = "[NonSend]: crate::NonSend
1385[NonSync]: crate::NonSync
1386[NonSendSync]: crate::NonSendSync"
1387 )]
1388 #[inline]
1389 #[track_caller]
1390 pub fn iter<T: IterComponent>(&self) -> IntoIterRef<'_, T> {
1391 let (all_storages, all_borrow) = unsafe {
1392 ARef::destructure(
1393 self.all_storages
1394 .borrow()
1395 .map_err(error::GetStorage::AllStoragesBorrow)
1396 .unwrap(),
1397 )
1398 };
1399
1400 let current = self.get_current();
1401
1402 IntoIterRef {
1403 all_storages,
1404 all_borrow: Some(all_borrow),
1405 current,
1406 phantom: core::marker::PhantomData,
1407 }
1408 }
1409
1410 #[track_caller]
1422 pub fn on_deletion(&self, f: impl FnMut(EntityId) + Send + Sync + 'static) {
1423 let mut entities = self.borrow::<EntitiesViewMut<'_>>().unwrap();
1424
1425 entities.on_deletion(f);
1426 }
1427
1428 pub fn is_entity_alive(&mut self, entity: EntityId) -> bool {
1430 self.all_storages
1431 .get_mut()
1432 .exclusive_storage_mut::<Entities>()
1433 .unwrap()
1434 .is_alive(entity)
1435 }
1436
1437 #[inline]
1456 #[track_caller]
1457 pub fn move_entity(&mut self, other: &mut World, entity: EntityId) {
1458 let other_all_storages = other.all_storages.get_mut();
1459
1460 self.all_storages
1461 .get_mut()
1462 .move_entity(other_all_storages, entity);
1463 }
1464
1465 #[inline]
1485 pub fn move_components(&mut self, other: &mut World, from: EntityId, to: EntityId) {
1486 let other_all_storages = other.all_storages.get_mut();
1487
1488 self.all_storages
1489 .get_mut()
1490 .move_components(other_all_storages, from, to);
1491 }
1492}
1493
1494impl core::fmt::Debug for World {
1495 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1496 let mut debug_struct = f.debug_tuple("World");
1497
1498 if let Ok(all_storages) = self.all_storages.borrow() {
1499 debug_struct.field(&*all_storages);
1500 } else {
1501 debug_struct.field(&"Could not borrow AllStorages");
1502 }
1503
1504 if let Ok(scheduler) = self.scheduler.borrow() {
1505 debug_struct.field(&*scheduler);
1506 } else {
1507 debug_struct.field(&"Could not borrow Scheduler");
1508 }
1509
1510 debug_struct.finish()
1511 }
1512}
1513
1514impl core::fmt::Debug for WorldMemoryUsage<'_> {
1515 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1516 if let Ok(all_storages) = self.0.all_storages.borrow() {
1517 all_storages.memory_usage().fmt(f)
1518 } else {
1519 f.write_str("Could not borrow AllStorages")
1520 }
1521 }
1522}