bevy_ecs/world/
identifier.rs1use crate::{
2 change_detection::Tick,
3 storage::SparseSetIndex,
4 system::{SystemAccess, SystemMeta, SystemParam, SystemParamValidationError},
5 world::{unsafe_world_cell::UnsafeWorldCell, FromWorld, World},
6};
7use bevy_platform::sync::atomic::{AtomicUsize, Ordering};
8
9#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
10pub struct WorldId(usize);
17
18static MAX_WORLD_ID: AtomicUsize = AtomicUsize::new(0);
20
21impl WorldId {
22 pub fn new() -> Option<Self> {
28 #[cfg(feature = "std")]
32 {
33 MAX_WORLD_ID
34 .try_update(Ordering::Relaxed, Ordering::Relaxed, |val| {
36 val.checked_add(1)
37 })
38 .map(WorldId)
39 .ok()
40 }
41 #[cfg(not(feature = "std"))]
42 {
43 MAX_WORLD_ID
44 .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |val| {
46 val.checked_add(1)
47 })
48 .map(WorldId)
49 .ok()
50 }
51 }
52}
53
54impl FromWorld for WorldId {
55 #[inline]
56 fn from_world(world: &mut World) -> Self {
57 world.id()
58 }
59}
60
61unsafe impl SystemParam for WorldId {
63 type State = ();
64
65 type Item<'world, 'state> = WorldId;
66
67 fn init_state(_: &mut World) -> Self::State {}
68
69 fn init_access(
70 _state: &Self::State,
71 system_meta: &mut SystemMeta,
72 system_access: &mut SystemAccess,
73 _world: &mut World,
74 ) {
75 system_access.require_shared_access::<Self>(system_meta);
76 }
77
78 #[inline]
79 unsafe fn get_param<'world, 'state>(
80 _: &'state mut Self::State,
81 _: &SystemMeta,
82 world: UnsafeWorldCell<'world>,
83 _: Tick,
84 ) -> Result<Self::Item<'world, 'state>, SystemParamValidationError> {
85 Ok(world.id())
86 }
87}
88
89impl SparseSetIndex for WorldId {
90 #[inline]
91 fn sparse_set_index(&self) -> usize {
92 self.0
93 }
94
95 #[inline]
96 fn get_sparse_set_index(value: usize) -> Self {
97 Self(value)
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use crate::system::assert_is_system;
104
105 use super::*;
106 use alloc::vec::Vec;
107
108 #[test]
109 fn world_ids_unique() {
110 let ids = core::iter::repeat_with(WorldId::new)
111 .take(50)
112 .map(Option::unwrap)
113 .collect::<Vec<_>>();
114 for (i, &id1) in ids.iter().enumerate() {
115 for &id2 in ids.iter().skip(i + 1) {
117 assert_ne!(id1, id2, "WorldIds should not repeat");
118 }
119 }
120 }
121
122 #[test]
123 fn world_id_system_param() {
124 fn test_system(world_id: WorldId) -> WorldId {
125 world_id
126 }
127
128 let mut world = World::default();
129 let system_id = world.register_system(test_system);
130 let world_id = world.run_system(system_id).unwrap();
131 assert_eq!(world.id(), world_id);
132 }
133
134 #[test]
135 #[should_panic]
136 fn world_id_cannot_be_exclusive_system_param() {
137 fn test_system(_world: &mut World, world_id: WorldId) -> WorldId {
138 world_id
139 }
140 assert_is_system(test_system);
141 }
142
143 }