Skip to main content

bevy_utils/
atomic_id.rs

1/// Defines a 32-bit id type which guarantees global uniqueness via atomics on a static global.
2///
3/// Note that this means the id space is process-wide, as such it may potentially be exhausted
4/// by a combination of long-running processes and multiple bevy `World`s, at which point we panic.
5#[macro_export]
6macro_rules! define_atomic_id {
7    ($atomic_id_type:ident) => {
8        /// Globally unique 32-bit id, guaranteed via atomics on a static global.
9        ///
10        /// Note that this means the id space is process-wide, as such it may potentially be exhausted
11        /// by a combination of long-running processes and multiple bevy `World`s, at which point we panic.
12        #[derive(Copy, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)]
13        pub struct $atomic_id_type(core::num::NonZero<u32>);
14
15        impl $atomic_id_type {
16            /// Creates a new id via fetch_add atomic on a static global.
17            #[expect(
18                clippy::new_without_default,
19                reason = "Implementing the `Default` trait on atomic IDs would imply that two `<AtomicIdType>::default()` equal each other. By only implementing `new()`, we indicate that each atomic ID created will be unique."
20            )]
21            pub fn new() -> Self {
22                use core::sync::atomic::{AtomicU32, Ordering};
23
24                static COUNTER: AtomicU32 = AtomicU32::new(1);
25
26                let counter = COUNTER.fetch_add(1, Ordering::Relaxed);
27                Self(core::num::NonZero::<u32>::new(counter).unwrap_or_else(|| {
28                    panic!(
29                        "The system ran out of unique `{}`s.",
30                        stringify!($atomic_id_type)
31                    );
32                }))
33            }
34        }
35
36        impl From<$atomic_id_type> for core::num::NonZero<u32> {
37            fn from(value: $atomic_id_type) -> Self {
38                value.0
39            }
40        }
41
42        impl From<core::num::NonZero<u32>> for $atomic_id_type {
43            fn from(value: core::num::NonZero<u32>) -> Self {
44                Self(value)
45            }
46        }
47    };
48}