1mod builder;
2mod run_batches;
3
4pub use builder::WorldBuilder;
5
6use crate::all_storages::{
7 AllStorages, CustomStorageAccess, TupleClone, TupleDeleteAny, TupleRetainStorage,
8};
9use crate::atomic_refcell::{ARef, ARefMut, AtomicRefCell};
10use crate::borrow::WorldBorrow;
11use crate::component::{Component, Unique};
12use crate::entities::Entities;
13use crate::entity_id::EntityId;
14use crate::error;
15use crate::get_component::GetComponent;
16use crate::get_unique::GetUnique;
17use crate::iter::{ShiperatorCaptain, ShiperatorSailor};
18use crate::iter_component::{into_iter, IntoIterRef, IterComponent};
19use crate::memory_usage::WorldMemoryUsage;
20use crate::r#mut::Mut;
21use crate::reserve::BulkEntityIter;
22use crate::scheduler::info::WorkloadsInfo;
23use crate::scheduler::{AsLabel, Batches, Label, Scheduler};
24use crate::sparse_set::{BulkAddEntity, TupleAddComponent, TupleDelete, TupleRemove};
25use crate::storage::{Storage, StorageId};
26use crate::system::System;
27use crate::tracking::{TrackingTimestamp, TupleTrack};
28use crate::views::EntitiesViewMut;
29use alloc::boxed::Box;
30use alloc::format;
31use alloc::sync::Arc;
32use core::sync::atomic::AtomicU64;
33
34pub struct World {
36 pub(crate) all_storages: AtomicRefCell<AllStorages>,
37 pub(crate) scheduler: AtomicRefCell<Scheduler>,
38 counter: Arc<AtomicU64>,
39 #[cfg(feature = "parallel")]
40 thread_pool: Option<rayon::ThreadPool>,
41}
42
43#[cfg(feature = "std")]
44impl Default for World {
45 fn default() -> Self {
47 let counter = Arc::new(AtomicU64::new(1));
48 World {
49 #[cfg(not(feature = "thread_local"))]
50 all_storages: AtomicRefCell::new(AllStorages::new(counter.clone())),
51 #[cfg(feature = "thread_local")]
52 all_storages: AtomicRefCell::new_non_send(
53 AllStorages::new(counter.clone()),
54 Arc::new(crate::std_thread_id_generator),
55 ),
56 scheduler: AtomicRefCell::new(Default::default()),
57 counter,
58 #[cfg(feature = "parallel")]
59 thread_pool: None,
60 }
61 }
62}
63
64#[cfg(feature = "std")]
65impl Clone for World {
66 #[track_caller]
67 fn clone(&self) -> Self {
68 let mut other = World::new();
69
70 let other_all_storages = other.all_storages.get_mut();
71
72 self.all_storages
73 .borrow()
74 .unwrap()
75 .clone_storages_to(other_all_storages);
76
77 other
78 }
79}
80
81impl World {
82 #[cfg(feature = "std")]
84 pub fn new() -> World {
85 Default::default()
86 }
87 #[cfg(feature = "parallel")]
89 pub fn remove_local_thread_pool(&mut self) -> Option<rayon::ThreadPool> {
90 self.thread_pool.take()
91 }
92 #[track_caller]
123 pub fn add_unique<T: Send + Sync + Unique>(&self, component: T) {
124 self.all_storages.borrow().unwrap().add_unique(component);
125 }
126 #[cfg(feature = "thread_local")]
160 #[cfg_attr(docsrs, doc(cfg(feature = "thread_local")))]
161 #[track_caller]
162 pub fn add_unique_non_send<T: Sync + Unique>(&self, component: T) {
163 self.all_storages
164 .borrow()
165 .unwrap()
166 .add_unique_non_send(component);
167 }
168 #[cfg(feature = "thread_local")]
202 #[cfg_attr(docsrs, doc(cfg(feature = "thread_local")))]
203 #[track_caller]
204 pub fn add_unique_non_sync<T: Send + Unique>(&self, component: T) {
205 self.all_storages
206 .borrow()
207 .unwrap()
208 .add_unique_non_sync(component);
209 }
210 #[cfg(feature = "thread_local")]
244 #[cfg_attr(docsrs, doc(cfg(feature = "thread_local")))]
245 #[track_caller]
246 pub fn add_unique_non_send_sync<T: Unique>(&self, component: T) {
247 self.all_storages
248 .borrow()
249 .unwrap()
250 .add_unique_non_send_sync(component);
251 }
252 pub fn remove_unique<T: Unique>(&self) -> Result<T, error::UniqueRemove> {
283 self.all_storages
284 .borrow()
285 .map_err(|_| error::UniqueRemove::AllStorages)?
286 .remove_unique::<T>()
287 }
288 #[doc = "Borrows the requested storages, if they don't exist they'll get created.
289You can use a tuple to get multiple storages at once.
290
291You can use:
292* [View]\\<T\\> for a shared access to `T` storage
293* [ViewMut]\\<T\\> for an exclusive access to `T` storage
294* [EntitiesView] for a shared access to the entity storage
295* [EntitiesViewMut] for an exclusive reference to the entity storage
296* [AllStoragesViewMut] for an exclusive access to the storage of all components, ⚠️ can't coexist with any other storage borrow
297* [UniqueView]\\<T\\> for a shared access to a `T` unique storage
298* [UniqueViewMut]\\<T\\> for an exclusive access to a `T` unique storage
299* `Option<V>` with one or multiple views for fallible access to one or more storages"]
300 #[cfg_attr(
301 all(feature = "thread_local", docsrs),
302 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>"
303 )]
304 #[cfg_attr(
305 all(feature = "thread_local", docsrs),
306 doc = " * [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
307 * [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
308[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
309 )]
310 #[cfg_attr(
311 all(feature = "thread_local", not(docsrs)),
312 doc = "* [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
313* [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
314[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
315 )]
316 #[cfg_attr(
317 not(feature = "thread_local"),
318 doc = "* NonSend: must activate the *thread_local* feature"
319 )]
320 #[cfg_attr(
321 all(feature = "thread_local", docsrs),
322 doc = " * [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
323 * [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
324[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
325 )]
326 #[cfg_attr(
327 all(feature = "thread_local", not(docsrs)),
328 doc = "* [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
329* [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
330[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
331 )]
332 #[cfg_attr(
333 not(feature = "thread_local"),
334 doc = "* NonSync: must activate the *thread_local* feature"
335 )]
336 #[cfg_attr(
337 all(feature = "thread_local", docsrs),
338 doc = " * [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
339 * [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
340[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
341 )]
342 #[cfg_attr(
343 all(feature = "thread_local", not(docsrs)),
344 doc = "* [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
345* [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
346[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
347 )]
348 #[cfg_attr(
349 not(feature = "thread_local"),
350 doc = "* NonSendSync: must activate the *thread_local* feature"
351 )]
352 #[doc = "
353### Borrows
354
355- [AllStorages] (exclusive) when requesting [AllStoragesViewMut]
356- [AllStorages] (shared) + storage (exclusive or shared) for all other views
357
358### Errors
359
360- [AllStorages] borrow failed.
361- Storage borrow failed.
362- Unique storage did not exist.
363
364### Example
365```
366use shipyard::{Component, EntitiesView, View, ViewMut, World};
367
368#[derive(Component)]
369struct U32(u32);
370
371#[derive(Component)]
372struct USIZE(usize);
373
374let world = World::new();
375
376let u32s = world.borrow::<View<U32>>().unwrap();
377let (entities, mut usizes) = world
378 .borrow::<(EntitiesView, ViewMut<USIZE>)>()
379 .unwrap();
380```
381[AllStorages]: crate::all_storages::AllStorages
382[EntitiesView]: crate::EntitiesView
383[EntitiesViewMut]: crate::EntitiesViewMut
384[AllStoragesViewMut]: crate::AllStoragesViewMut
385[World]: crate::World
386[View]: crate::View
387[ViewMut]: crate::ViewMut
388[UniqueView]: crate::UniqueView
389[UniqueViewMut]: crate::UniqueViewMut"]
390 #[cfg_attr(feature = "thread_local", doc = "[NonSend]: crate::borrow::NonSend")]
391 #[cfg_attr(feature = "thread_local", doc = "[NonSync]: crate::borrow::NonSync")]
392 #[cfg_attr(
393 feature = "thread_local",
394 doc = "[NonSendSync]: crate::borrow::NonSendSync"
395 )]
396 pub fn borrow<V: WorldBorrow>(&self) -> Result<V::WorldView<'_>, error::GetStorage> {
397 let current = self.get_current();
398
399 V::world_borrow(self, None, current)
400 }
401 #[doc = "Borrows the requested storages, runs the function and evaluates to the function's return value.
402Data can be passed to the function, this always has to be a single type but you can use a tuple if needed.
403
404You can use:
405* [View]\\<T\\> for a shared access to `T` storage
406* [ViewMut]\\<T\\> for an exclusive access to `T` storage
407* [EntitiesView] for a shared access to the entity storage
408* [EntitiesViewMut] for an exclusive reference to the entity storage
409* [AllStoragesViewMut] for an exclusive access to the storage of all components, ⚠️ can't coexist with any other storage borrow
410* [UniqueView]\\<T\\> for a shared access to a `T` unique storage
411* [UniqueViewMut]\\<T\\> for an exclusive access to a `T` unique storage
412* `Option<V>` with one or multiple views for fallible access to one or more storages"]
413 #[cfg_attr(
414 all(feature = "thread_local", docsrs),
415 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>"
416 )]
417 #[cfg_attr(
418 all(feature = "thread_local", docsrs),
419 doc = " * [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
420 * [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
421[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
422 )]
423 #[cfg_attr(
424 all(feature = "thread_local", not(docsrs)),
425 doc = "* [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
426* [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
427[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
428 )]
429 #[cfg_attr(
430 not(feature = "thread_local"),
431 doc = "* NonSend: must activate the *thread_local* feature"
432 )]
433 #[cfg_attr(
434 all(feature = "thread_local", docsrs),
435 doc = " * [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
436 * [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
437[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
438 )]
439 #[cfg_attr(
440 all(feature = "thread_local", not(docsrs)),
441 doc = "* [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
442* [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
443[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
444 )]
445 #[cfg_attr(
446 not(feature = "thread_local"),
447 doc = "* NonSync: must activate the *thread_local* feature"
448 )]
449 #[cfg_attr(
450 all(feature = "thread_local", docsrs),
451 doc = " * [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
452 * [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
453[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
454 )]
455 #[cfg_attr(
456 all(feature = "thread_local", not(docsrs)),
457 doc = "* [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
458* [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
459[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
460 )]
461 #[cfg_attr(
462 not(feature = "thread_local"),
463 doc = "* NonSendSync: must activate the *thread_local* feature"
464 )]
465 #[doc = "
466### Borrows
467
468- [AllStorages] (exclusive) when requesting [AllStoragesViewMut]
469- [AllStorages] (shared) + storage (exclusive or shared) for all other views
470
471### Panics
472
473- [AllStorages] borrow failed.
474- Storage borrow failed.
475- Unique storage did not exist.
476- Error returned by user.
477
478### Example
479```
480use shipyard::{Component, EntityId, Get, ViewMut, World};
481
482#[derive(Component)]
483struct Position([f32; 2]);
484
485fn sys1((entity, [x, y]): (EntityId, [f32; 2]), mut positions: ViewMut<Position>) {
486 if let Ok(mut pos) = (&mut positions).get(entity) {
487 pos.0 = [x, y];
488 }
489}
490
491let world = World::new();
492
493world.run_with_data(sys1, (EntityId::dead(), [0., 0.]));
494```
495[AllStorages]: crate::all_storages::AllStorages
496[EntitiesView]: crate::EntitiesView
497[EntitiesViewMut]: crate::EntitiesViewMut
498[AllStoragesViewMut]: crate::AllStoragesViewMut
499[World]: crate::World
500[View]: crate::View
501[ViewMut]: crate::ViewMut
502[UniqueView]: crate::UniqueView
503[UniqueViewMut]: crate::UniqueViewMut"]
504 #[cfg_attr(feature = "thread_local", doc = "[NonSend]: crate::borrow::NonSend")]
505 #[cfg_attr(feature = "thread_local", doc = "[NonSync]: crate::borrow::NonSync")]
506 #[cfg_attr(
507 feature = "thread_local",
508 doc = "[NonSendSync]: crate::borrow::NonSendSync"
509 )]
510 #[track_caller]
511 pub fn run_with_data<Data, B, S: System<(Data,), B>>(
512 &self,
513 system: S,
514 data: Data,
515 ) -> S::Return {
516 #[cfg(feature = "tracing")]
517 let system_span = tracing::info_span!("system", name = ?core::any::type_name::<S>());
518 #[cfg(feature = "tracing")]
519 let _system_span = system_span.enter();
520
521 system
522 .run((data,), self)
523 .map_err(error::Run::GetStorage)
524 .unwrap()
525 }
526 #[doc = "Borrows the requested storages, runs the function and evaluates to the function's return value.
527
528You can use:
529* [View]\\<T\\> for a shared access to `T` storage
530* [ViewMut]\\<T\\> for an exclusive access to `T` storage
531* [EntitiesView] for a shared access to the entity storage
532* [EntitiesViewMut] for an exclusive reference to the entity storage
533* [AllStoragesViewMut] for an exclusive access to the storage of all components, ⚠️ can't coexist with any other storage borrow
534* [UniqueView]\\<T\\> for a shared access to a `T` unique storage
535* [UniqueViewMut]\\<T\\> for an exclusive access to a `T` unique storage
536* `Option<V>` with one or multiple views for fallible access to one or more storages"]
537 #[cfg_attr(
538 all(feature = "thread_local", docsrs),
539 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>"
540 )]
541 #[cfg_attr(
542 all(feature = "thread_local", docsrs),
543 doc = " * [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
544 * [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
545[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
546 )]
547 #[cfg_attr(
548 all(feature = "thread_local", not(docsrs)),
549 doc = "* [NonSend]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send`
550* [NonSend]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send`
551[NonSend] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send` unique storage."
552 )]
553 #[cfg_attr(
554 not(feature = "thread_local"),
555 doc = "* NonSend: must activate the *thread_local* feature"
556 )]
557 #[cfg_attr(
558 all(feature = "thread_local", docsrs),
559 doc = " * [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
560 * [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
561[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
562 )]
563 #[cfg_attr(
564 all(feature = "thread_local", not(docsrs)),
565 doc = "* [NonSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Sync`
566* [NonSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Sync`
567[NonSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Sync` unique storage."
568 )]
569 #[cfg_attr(
570 not(feature = "thread_local"),
571 doc = "* NonSync: must activate the *thread_local* feature"
572 )]
573 #[cfg_attr(
574 all(feature = "thread_local", docsrs),
575 doc = " * [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
576 * [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
577[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
578 )]
579 #[cfg_attr(
580 all(feature = "thread_local", not(docsrs)),
581 doc = "* [NonSendSync]<[View]\\<T\\>> for a shared access to a `T` storage where `T` isn't `Send` nor `Sync`
582* [NonSendSync]<[ViewMut]\\<T\\>> for an exclusive access to a `T` storage where `T` isn't `Send` nor `Sync`
583[NonSendSync] and [UniqueView]/[UniqueViewMut] can be used together to access a `!Send + !Sync` unique storage."
584 )]
585 #[cfg_attr(
586 not(feature = "thread_local"),
587 doc = "* NonSendSync: must activate the *thread_local* feature"
588 )]
589 #[doc = "
590### Borrows
591
592- [AllStorages] (exclusive) when requesting [AllStoragesViewMut]
593- [AllStorages] (shared) + storage (exclusive or shared) for all other views
594
595### Panics
596
597- [AllStorages] borrow failed.
598- Storage borrow failed.
599- Unique storage did not exist.
600- Error returned by user.
601
602### Example
603```
604use shipyard::{Component, View, ViewMut, World};
605
606#[derive(Component)]
607struct I32(i32);
608
609#[derive(Component)]
610struct USIZE(usize);
611
612#[derive(Component)]
613struct U32(u32);
614
615fn sys1(i32s: View<I32>) -> i32 {
616 0
617}
618
619let world = World::new();
620
621world
622 .run(|usizes: View<USIZE>, mut u32s: ViewMut<U32>| {
623 // -- snip --
624 });
625
626let i = world.run(sys1);
627```
628[AllStorages]: crate::all_storages::AllStorages
629[EntitiesView]: crate::EntitiesView
630[EntitiesViewMut]: crate::EntitiesViewMut
631[AllStoragesViewMut]: crate::AllStoragesViewMut
632[World]: crate::World
633[View]: crate::View
634[ViewMut]: crate::ViewMut
635[UniqueView]: crate::UniqueView
636[UniqueViewMut]: crate::UniqueViewMut"]
637 #[cfg_attr(feature = "thread_local", doc = "[NonSend]: crate::borrow::NonSend")]
638 #[cfg_attr(feature = "thread_local", doc = "[NonSync]: crate::borrow::NonSync")]
639 #[cfg_attr(
640 feature = "thread_local",
641 doc = "[NonSendSync]: crate::borrow::NonSendSync"
642 )]
643 #[track_caller]
644 pub fn run<B, S: System<(), B>>(&self, system: S) -> S::Return {
645 #[cfg(feature = "tracing")]
646 let system_span = tracing::info_span!("system", name = ?core::any::type_name::<S>());
647 #[cfg(feature = "tracing")]
648 let _system_span = system_span.enter();
649
650 system
651 .run((), self)
652 .map_err(error::Run::GetStorage)
653 .unwrap()
654 }
655 pub fn set_default_workload<T>(
666 &self,
667 name: impl AsLabel<T>,
668 ) -> Result<(), error::SetDefaultWorkload> {
669 self.scheduler
670 .borrow_mut()
671 .map_err(|_| error::SetDefaultWorkload::Borrow)?
672 .set_default(name.as_label())
673 }
674 #[track_caller]
684 pub fn rename_workload<T, U>(&self, old_name: impl AsLabel<T>, new_name: impl AsLabel<U>) {
685 let old_label = old_name.as_label();
686 let new_label = new_name.as_label();
687
688 self.scheduler
689 .borrow_mut()
690 .unwrap()
691 .rename(&old_label, Box::new(new_label));
692 }
693 pub fn run_workload<T>(&self, label: impl AsLabel<T>) -> Result<(), error::RunWorkload> {
707 let scheduler = self
708 .scheduler
709 .borrow()
710 .map_err(|_| error::RunWorkload::Scheduler)?;
711
712 let label = label.as_label();
713 let batches = scheduler.workload(&*label)?;
714
715 self.run_batches(
716 &scheduler.systems,
717 &scheduler.system_names,
718 batches,
719 &*label,
720 )
721 }
722 #[track_caller]
744 pub fn contains_workload<T>(&self, name: impl AsLabel<T>) -> bool {
745 let label = name.as_label();
746
747 self.scheduler.borrow().unwrap().contains_workload(&*label)
748 }
749 #[allow(clippy::type_complexity)]
750 pub(crate) fn run_batches(
751 &self,
752 systems: &[Box<dyn Fn(&World) -> Result<(), error::Run> + Send + Sync + 'static>],
753 system_names: &[Box<dyn Label>],
754 batches: &Batches,
755 workload_name: &dyn Label,
756 ) -> Result<(), error::RunWorkload> {
757 if let Some(run_if) = &batches.workload_run_if {
758 if !run_if
759 .run(self)
760 .map_err(|err| error::RunWorkload::Run((workload_name.dyn_clone(), err)))?
761 {
762 return Ok(());
763 }
764 }
765
766 #[cfg(feature = "parallel")]
767 {
768 self.run_batches_parallel(systems, system_names, batches, workload_name)
769 }
770
771 #[cfg(not(feature = "parallel"))]
772 {
773 self.run_batches_sequential(systems, system_names, batches, workload_name)
774 }
775 }
776 pub fn run_default_workload(&self) -> Result<(), error::RunWorkload> {
789 let scheduler = self
790 .scheduler
791 .borrow()
792 .map_err(|_| error::RunWorkload::Scheduler)?;
793
794 if !scheduler.is_empty() {
795 self.run_batches(
796 &scheduler.systems,
797 &scheduler.system_names,
798 scheduler.default_workload(),
799 &scheduler.default,
800 )?
801 }
802 Ok(())
803 }
804 pub fn all_storages(&self) -> Result<ARef<'_, &'_ AllStorages>, error::Borrow> {
811 self.all_storages.borrow()
812 }
813 pub fn all_storages_mut(&self) -> Result<ARefMut<'_, &'_ mut AllStorages>, error::Borrow> {
820 self.all_storages.borrow_mut()
821 }
822 pub fn add_custom_storage<S: 'static + Storage + Send + Sync>(
828 &self,
829 storage_id: StorageId,
830 storage: S,
831 ) -> Result<(), error::Borrow> {
832 let _ = self
833 .all_storages
834 .borrow()?
835 .custom_storage_or_insert_by_id(storage_id, || storage);
836
837 Ok(())
838 }
839
840 #[inline]
842 pub(crate) fn get_current(&self) -> TrackingTimestamp {
843 TrackingTimestamp::new(
844 self.counter
845 .fetch_add(1, core::sync::atomic::Ordering::Acquire),
846 )
847 }
848
849 pub fn get_tracking_timestamp(&self) -> TrackingTimestamp {
851 TrackingTimestamp::new(self.counter.load(core::sync::atomic::Ordering::Acquire))
852 }
853}
854
855impl World {
856 #[inline]
876 #[track_caller]
877 pub fn add_entity<C: TupleAddComponent>(&mut self, component: C) -> EntityId {
878 self.all_storages.get_mut().add_entity(component)
879 }
880 #[inline]
899 #[track_caller]
900 pub fn bulk_add_entity<T: BulkAddEntity>(&mut self, source: T) -> BulkEntityIter<'_> {
901 self.all_storages.get_mut().bulk_add_entity(source)
902 }
903 #[inline]
932 #[track_caller]
933 pub fn add_component<C: TupleAddComponent>(&mut self, entity: EntityId, component: C) {
934 self.all_storages.get_mut().add_component(entity, component)
935 }
936 #[inline]
957 #[track_caller]
958 pub fn delete_component<C: TupleDelete>(&mut self, entity: EntityId) {
959 self.all_storages.get_mut().delete_component::<C>(entity)
960 }
961 #[inline]
983 #[track_caller]
984 pub fn remove<C: TupleRemove>(&mut self, entity: EntityId) -> C::Out {
985 self.all_storages.get_mut().remove::<C>(entity)
986 }
987 #[inline]
1007 #[track_caller]
1008 pub fn delete_entity(&mut self, entity: EntityId) -> bool {
1009 self.all_storages.get_mut().delete_entity(entity)
1010 }
1011 #[inline]
1031 #[track_caller]
1032 pub fn strip(&mut self, entity: EntityId) {
1033 self.all_storages.get_mut().strip(entity);
1034 }
1035
1036 #[inline]
1062 #[track_caller]
1063 pub fn bulk_strip<I: IntoIterator<Item = EntityId>>(&mut self, entities: I)
1064 where
1065 I::IntoIter: Clone,
1066 {
1067 self.all_storages.get_mut().bulk_strip(entities);
1068 }
1069
1070 #[inline]
1096 #[track_caller]
1097 #[cfg(all(feature = "parallel", not(feature = "thread_local")))]
1098 pub fn par_strip<I: IntoIterator<Item = EntityId>>(&mut self, entities: I)
1099 where
1100 I::IntoIter: Clone + Sync,
1101 {
1102 self.all_storages.get_mut().par_strip(entities);
1103 }
1104
1105 #[inline]
1135 #[track_caller]
1136 pub fn delete_any<S: TupleDeleteAny>(&mut self) {
1137 self.all_storages.get_mut().delete_any::<S>();
1138 }
1139 #[inline]
1161 #[track_caller]
1162 pub fn retain_storage<S: TupleRetainStorage>(&mut self, entity: EntityId) {
1163 self.all_storages.get_mut().retain_storage::<S>(entity);
1164 }
1165 #[inline]
1168 #[track_caller]
1169 pub fn retain_storage_by_id(&mut self, entity: EntityId, excluded_storage: &[StorageId]) {
1170 self.all_storages
1171 .get_mut()
1172 .retain_storage_by_id(entity, excluded_storage);
1173 }
1174 #[inline]
1186 #[track_caller]
1187 pub fn clear(&mut self) {
1188 self.all_storages.get_mut().clear();
1189 }
1190 #[track_caller]
1192 pub fn clear_all_removed_and_deleted(&mut self) {
1193 self.all_storages.get_mut().clear_all_removed_and_deleted()
1194 }
1195 #[track_caller]
1197 pub fn clear_all_removed_and_deleted_older_than_timestamp(
1198 &mut self,
1199 timestamp: TrackingTimestamp,
1200 ) {
1201 self.all_storages
1202 .get_mut()
1203 .clear_all_removed_and_deleted_older_than_timestamp(timestamp)
1204 }
1205 #[track_caller]
1207 pub fn clear_all_inserted(&mut self) {
1208 self.all_storages.get_mut().clear_all_inserted()
1209 }
1210 #[track_caller]
1212 pub fn clear_all_modified(&mut self) {
1213 self.all_storages.get_mut().clear_all_modified()
1214 }
1215 #[track_caller]
1217 pub fn clear_all_inserted_and_modified(&mut self) {
1218 self.all_storages
1219 .get_mut()
1220 .clear_all_inserted_and_modified()
1221 }
1222 #[inline]
1226 #[track_caller]
1227 pub fn spawn(&mut self, entity: EntityId) -> bool {
1228 self.all_storages.get_mut().spawn(entity)
1229 }
1230
1231 #[track_caller]
1237 pub fn retain<T: Component + Send + Sync>(&mut self, f: impl FnMut(EntityId, &T) -> bool) {
1238 self.all_storages.get_mut().retain(f);
1239 }
1240
1241 #[track_caller]
1247 pub fn retain_mut<T: Component + Send + Sync>(
1248 &mut self,
1249 f: impl FnMut(EntityId, Mut<'_, T>) -> bool,
1250 ) {
1251 self.all_storages.get_mut().retain_mut(f);
1252 }
1253
1254 pub fn memory_usage(&self) -> WorldMemoryUsage<'_> {
1256 WorldMemoryUsage(self)
1257 }
1258
1259 #[track_caller]
1269 pub fn workloads_info(&self) -> WorkloadsInfo {
1270 let scheduler = self.scheduler.borrow().unwrap();
1271
1272 WorkloadsInfo(
1273 scheduler
1274 .workloads_info
1275 .iter()
1276 .map(|(name, workload_info)| (format!("{:?}", name), workload_info.clone()))
1277 .collect(),
1278 )
1279 }
1280
1281 #[track_caller]
1283 pub fn track_insertion<T: TupleTrack>(&mut self) -> &mut World {
1284 self.all_storages.get_mut().track_insertion::<T>();
1285 self
1286 }
1287
1288 #[track_caller]
1290 pub fn track_modification<T: TupleTrack>(&mut self) -> &mut World {
1291 self.all_storages.get_mut().track_modification::<T>();
1292 self
1293 }
1294
1295 #[track_caller]
1297 pub fn track_deletion<T: TupleTrack>(&mut self) -> &mut World {
1298 self.all_storages.get_mut().track_deletion::<T>();
1299 self
1300 }
1301
1302 #[track_caller]
1304 pub fn track_removal<T: TupleTrack>(&mut self) -> &mut World {
1305 self.all_storages.get_mut().track_removal::<T>();
1306 self
1307 }
1308
1309 #[track_caller]
1311 pub fn track_all<T: TupleTrack>(&mut self) {
1312 self.all_storages.get_mut().track_all::<T>();
1313 }
1314
1315 #[doc = "Retrieve components of `entity`.
1316
1317Multiple components can be queried at the same time using a tuple.
1318
1319You can use:
1320* `&T` for a shared access to `T` component
1321* `&mut T` for an exclusive access to `T` component"]
1322 #[cfg_attr(
1323 all(feature = "thread_local", docsrs),
1324 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>"
1325 )]
1326 #[cfg_attr(
1327 all(feature = "thread_local"),
1328 doc = "* [NonSend]<&T> for a shared access to a `T` component where `T` isn't `Send`
1329* [NonSend]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send`
1330* [NonSync]<&T> for a shared access to a `T` component where `T` isn't `Sync`
1331* [NonSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Sync`
1332* [NonSendSync]<&T> for a shared access to a `T` component where `T` isn't `Send` nor `Sync`
1333* [NonSendSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send` nor `Sync`"
1334 )]
1335 #[cfg_attr(
1336 not(feature = "thread_local"),
1337 doc = "* NonSend: must activate the *thread_local* feature
1338* NonSync: must activate the *thread_local* feature
1339* NonSendSync: must activate the *thread_local* feature"
1340 )]
1341 #[doc = "
1342### Borrows
1343
1344- [AllStorages] (shared) + storage (exclusive or shared)
1345
1346### Errors
1347
1348- [AllStorages] borrow failed.
1349- Storage borrow failed.
1350- Entity does not have the component.
1351
1352### Example
1353```
1354use shipyard::{Component, World};
1355
1356#[derive(Component, Debug, PartialEq, Eq)]
1357struct U32(u32);
1358
1359#[derive(Component, Debug, PartialEq, Eq)]
1360struct USIZE(usize);
1361
1362let mut world = World::new();
1363
1364let entity = world.add_entity((USIZE(0), U32(1)));
1365
1366let (i, j) = world.get::<(&USIZE, &mut U32)>(entity).unwrap();
1367
1368assert!(*i == &USIZE(0));
1369assert!(*j == &U32(1));
1370```"]
1371 #[cfg_attr(
1372 feature = "thread_local",
1373 doc = "[NonSend]: crate::borrow::NonSend
1374[NonSync]: crate::borrow::NonSync
1375[NonSendSync]: crate::borrow::NonSendSync"
1376 )]
1377 #[inline]
1378 pub fn get<T: GetComponent>(
1379 &self,
1380 entity: EntityId,
1381 ) -> Result<T::Out<'_>, error::GetComponent> {
1382 let (all_storages, all_borrow) = unsafe {
1383 ARef::destructure(
1384 self.all_storages
1385 .borrow()
1386 .map_err(error::GetStorage::AllStoragesBorrow)?,
1387 )
1388 };
1389
1390 let current = self.get_current();
1391
1392 T::get(all_storages, Some(all_borrow), current, entity)
1393 }
1394
1395 #[doc = "Retrieve a unique component.
1396
1397You can use:
1398* `&T` for a shared access to `T` unique component
1399* `&mut T` for an exclusive access to `T` unique component"]
1400 #[cfg_attr(
1401 all(feature = "thread_local", docsrs),
1402 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>"
1403 )]
1404 #[cfg_attr(
1405 all(feature = "thread_local"),
1406 doc = "* [NonSend]<&T> for a shared access to a `T` unique component where `T` isn't `Send`
1407* [NonSend]<&mut T> for an exclusive access to a `T` unique component where `T` isn't `Send`
1408* [NonSync]<&T> for a shared access to a `T` unique component where `T` isn't `Sync`
1409* [NonSync]<&mut T> for an exclusive access to a `T` unique component where `T` isn't `Sync`
1410* [NonSendSync]<&T> for a shared access to a `T` unique component where `T` isn't `Send` nor `Sync`
1411* [NonSendSync]<&mut T> for an exclusive access to a `T` unique component where `T` isn't `Send` nor `Sync`"
1412 )]
1413 #[cfg_attr(
1414 not(feature = "thread_local"),
1415 doc = "* NonSend: must activate the *thread_local* feature
1416* NonSync: must activate the *thread_local* feature
1417* NonSendSync: must activate the *thread_local* feature"
1418 )]
1419 #[doc = "
1420### Borrows
1421
1422- [AllStorages] (shared) + storage (exclusive or shared)
1423
1424### Errors
1425
1426- [AllStorages] borrow failed.
1427- Storage borrow failed.
1428
1429### Example
1430```
1431use shipyard::{Unique, World};
1432
1433#[derive(Unique, Debug, PartialEq, Eq)]
1434struct U32(u32);
1435
1436let mut world = World::new();
1437
1438world.add_unique(U32(0));
1439
1440let i = world.get_unique::<&U32>().unwrap();
1441
1442assert!(*i == U32(0));
1443```"]
1444 #[cfg_attr(
1445 feature = "thread_local",
1446 doc = "[NonSend]: crate::borrow::NonSend
1447[NonSync]: crate::borrow::NonSync
1448[NonSendSync]: crate::borrow::NonSendSync"
1449 )]
1450 #[inline]
1451 pub fn get_unique<T: GetUnique>(&self) -> Result<T::Out<'_>, error::GetStorage> {
1452 let (all_storages, all_borrow) = unsafe {
1453 ARef::destructure(
1454 self.all_storages
1455 .borrow()
1456 .map_err(error::GetStorage::AllStoragesBorrow)?,
1457 )
1458 };
1459
1460 T::get_unique(all_storages, Some(all_borrow))
1461 }
1462
1463 #[doc = "Iterate components.
1464
1465Multiple components can be iterated at the same time using a tuple.
1466
1467You can use:
1468* `&T` for a shared access to `T` component
1469* `&mut T` for an exclusive access to `T` component"]
1470 #[cfg_attr(
1471 all(feature = "thread_local", docsrs),
1472 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>"
1473 )]
1474 #[cfg_attr(
1475 all(feature = "thread_local"),
1476 doc = "* [NonSend]<&T> for a shared access to a `T` component where `T` isn't `Send`
1477* [NonSend]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send`
1478* [NonSync]<&T> for a shared access to a `T` component where `T` isn't `Sync`
1479* [NonSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Sync`
1480* [NonSendSync]<&T> for a shared access to a `T` component where `T` isn't `Send` nor `Sync`
1481* [NonSendSync]<&mut T> for an exclusive access to a `T` component where `T` isn't `Send` nor `Sync`"
1482 )]
1483 #[cfg_attr(
1484 not(feature = "thread_local"),
1485 doc = "* NonSend: must activate the *thread_local* feature
1486* NonSync: must activate the *thread_local* feature
1487* NonSendSync: must activate the *thread_local* feature"
1488 )]
1489 #[doc = "
1490### Borrows
1491
1492- [AllStorages] (shared)
1493
1494### Panics
1495
1496- [AllStorages] borrow failed.
1497
1498### Example
1499```
1500use shipyard::{Component, World};
1501
1502#[derive(Component, Debug, PartialEq, Eq)]
1503struct U32(u32);
1504
1505#[derive(Component, Debug, PartialEq, Eq)]
1506struct USIZE(usize);
1507
1508let mut world = World::new();
1509
1510let entity = world.add_entity((USIZE(0), U32(1)));
1511
1512let mut iter = world.iter::<(&USIZE, &mut U32)>();
1513
1514for (i, j) in &mut iter {
1515 // <-- SNIP -->
1516}
1517```"]
1518 #[cfg_attr(
1519 feature = "thread_local",
1520 doc = "[NonSend]: crate::borrow::NonSend
1521[NonSync]: crate::borrow::NonSync
1522[NonSendSync]: crate::borrow::NonSendSync"
1523 )]
1524 #[inline]
1525 #[track_caller]
1526 pub fn iter<'a, T: IterComponent>(&'a self) -> IntoIterRef<'a, T>
1527 where
1528 <T as IterComponent>::Shiperator<'a>: ShiperatorCaptain + ShiperatorSailor,
1529 {
1530 let (all_storages, all_borrow) = unsafe {
1531 ARef::destructure(
1532 self.all_storages
1533 .borrow()
1534 .map_err(error::GetStorage::AllStoragesBorrow)
1535 .unwrap(),
1536 )
1537 };
1538
1539 let current = self.get_current();
1540
1541 into_iter(all_storages, Some(all_borrow), current).unwrap()
1542 }
1543
1544 #[track_caller]
1556 pub fn on_deletion(&self, f: impl FnMut(EntityId) + Send + Sync + 'static) {
1557 let mut entities = self.borrow::<EntitiesViewMut<'_>>().unwrap();
1558
1559 entities.on_deletion(f);
1560 }
1561
1562 pub fn is_entity_alive(&mut self, entity: EntityId) -> bool {
1564 self.all_storages
1565 .get_mut()
1566 .exclusive_storage_mut::<Entities>()
1567 .unwrap()
1568 .is_alive(entity)
1569 }
1570
1571 #[inline]
1596 #[track_caller]
1597 pub fn move_entity(&mut self, other: &mut World, entity: EntityId) {
1598 let other_all_storages = other.all_storages.get_mut();
1599
1600 self.all_storages
1601 .get_mut()
1602 .move_entity(other_all_storages, entity);
1603 }
1604
1605 #[inline]
1632 #[track_caller]
1633 pub fn move_components(&mut self, other: &mut World, from: EntityId, to: EntityId) {
1634 let other_all_storages = other.all_storages.get_mut();
1635
1636 self.all_storages
1637 .get_mut()
1638 .move_components(other_all_storages, from, to);
1639 }
1640
1641 #[inline]
1664 #[track_caller]
1665 pub fn register_clone<T: TupleClone>(&mut self) {
1666 self.all_storages.get_mut().register_clone::<T>();
1667 }
1668
1669 #[inline]
1700 #[track_caller]
1701 pub fn clone_entity_to(&self, other: &mut World, entity: EntityId) {
1702 let other_all_storages = other.all_storages.get_mut();
1703
1704 self.all_storages
1705 .borrow()
1706 .unwrap()
1707 .clone_entity_to(other_all_storages, entity);
1708 }
1709
1710 #[inline]
1745 #[track_caller]
1746 pub fn clone_components_to(&self, other: &mut World, from: EntityId, to: EntityId) {
1747 let other_all_storages = other.all_storages.get_mut();
1748
1749 self.all_storages
1750 .borrow()
1751 .unwrap()
1752 .clone_components_to(other_all_storages, from, to);
1753 }
1754}
1755
1756impl core::fmt::Debug for World {
1757 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1758 let mut debug_struct = f.debug_tuple("World");
1759
1760 if let Ok(all_storages) = self.all_storages.borrow() {
1761 debug_struct.field(&*all_storages);
1762 } else {
1763 debug_struct.field(&"Could not borrow AllStorages");
1764 }
1765
1766 if let Ok(scheduler) = self.scheduler.borrow() {
1767 debug_struct.field(&*scheduler);
1768 } else {
1769 debug_struct.field(&"Could not borrow Scheduler");
1770 }
1771
1772 debug_struct.finish()
1773 }
1774}
1775
1776impl core::fmt::Debug for WorldMemoryUsage<'_> {
1777 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1778 if let Ok(all_storages) = self.0.all_storages.borrow() {
1779 all_storages.memory_usage().fmt(f)
1780 } else {
1781 f.write_str("Could not borrow AllStorages")
1782 }
1783 }
1784}
1785
1786#[cfg(feature = "serde1")]
1787impl World {
1788 pub fn serialize<'w, S: serde::Serializer, V: WorldBorrow>(
1811 &'w self,
1812 serializer: S,
1813 ) -> Result<S::Ok, error::Serialize<S>>
1814 where
1815 V::WorldView<'w>: serde::Serialize,
1816 {
1817 use serde::Serialize;
1818
1819 match self.borrow::<V>() {
1820 Ok(view) => match view.serialize(serializer) {
1821 Ok(ok) => Ok(ok),
1822 Err(err) => Err(error::Serialize::Serialization(err)),
1823 },
1824 Err(err) => Err(error::Serialize::Borrow(err)),
1825 }
1826 }
1827
1828 pub fn deserialize<'w, 'de, D: serde::Deserializer<'de>, V: WorldBorrow>(
1860 &'w self,
1861 deserializer: D,
1862 ) -> Result<(), error::Deserialize<'de, D>>
1863 where
1864 V::WorldView<'w>: serde::Deserialize<'de>,
1865 {
1866 match self.borrow::<V>() {
1867 Ok(mut view) => match serde::Deserialize::deserialize_in_place(deserializer, &mut view)
1868 {
1869 Ok(ok) => Ok(ok),
1870 Err(err) => Err(error::Deserialize::Deserialization(err)),
1871 },
1872 Err(err) => Err(error::Deserialize::Borrow(err)),
1873 }
1874 }
1875}