bevy_ecs/world/
identifier.rs1use crate::{
2 component::Tick,
3 query::FilteredAccessSet,
4 storage::SparseSetIndex,
5 system::{ExclusiveSystemParam, ReadOnlySystemParam, SystemMeta, SystemParam},
6 world::{FromWorld, World},
7};
8use bevy_platform::sync::atomic::{AtomicUsize, Ordering};
9
10use super::unsafe_world_cell::UnsafeWorldCell;
11
12#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
13pub struct WorldId(usize);
20
21static MAX_WORLD_ID: AtomicUsize = AtomicUsize::new(0);
23
24impl WorldId {
25 pub fn new() -> Option<Self> {
31 MAX_WORLD_ID
32 .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |val| {
34 val.checked_add(1)
35 })
36 .map(WorldId)
37 .ok()
38 }
39}
40
41impl FromWorld for WorldId {
42 #[inline]
43 fn from_world(world: &mut World) -> Self {
44 world.id()
45 }
46}
47
48unsafe impl ReadOnlySystemParam for WorldId {}
50
51unsafe impl SystemParam for WorldId {
53 type State = ();
54
55 type Item<'world, 'state> = WorldId;
56
57 fn init_state(_: &mut World) -> Self::State {}
58
59 fn init_access(
60 _state: &Self::State,
61 _system_meta: &mut SystemMeta,
62 _component_access_set: &mut FilteredAccessSet,
63 _world: &mut World,
64 ) {
65 }
66
67 #[inline]
68 unsafe fn get_param<'world, 'state>(
69 _: &'state mut Self::State,
70 _: &SystemMeta,
71 world: UnsafeWorldCell<'world>,
72 _: Tick,
73 ) -> Self::Item<'world, 'state> {
74 world.id()
75 }
76}
77
78impl ExclusiveSystemParam for WorldId {
79 type State = WorldId;
80 type Item<'s> = WorldId;
81
82 fn init(world: &mut World, _system_meta: &mut SystemMeta) -> Self::State {
83 world.id()
84 }
85
86 fn get_param<'s>(state: &'s mut Self::State, _system_meta: &SystemMeta) -> Self::Item<'s> {
87 *state
88 }
89}
90
91impl SparseSetIndex for WorldId {
92 #[inline]
93 fn sparse_set_index(&self) -> usize {
94 self.0
95 }
96
97 #[inline]
98 fn get_sparse_set_index(value: usize) -> Self {
99 Self(value)
100 }
101}
102
103#[cfg(test)]
104mod tests {
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 fn world_id_exclusive_system_param() {
136 fn test_system(_world: &mut World, world_id: WorldId) -> WorldId {
137 world_id
138 }
139
140 let mut world = World::default();
141 let system_id = world.register_system(test_system);
142 let world_id = world.run_system(system_id).unwrap();
143 assert_eq!(world.id(), world_id);
144 }
145
146 }