bevy_ecs/entity/mod.rs
1//! Entity handling types.
2//!
3//! An **entity** exclusively owns zero or more [component] instances, all of different types, and can dynamically acquire or lose them over its lifetime.
4//!
5//! **empty entity**: Entity with zero components.
6//! **pending entity**: Entity reserved, but not flushed yet (see [`Entities::flush`] docs for reference).
7//! **reserved entity**: same as **pending entity**.
8//! **invalid entity**: **pending entity** flushed with invalid (see [`Entities::flush_as_invalid`] docs for reference).
9//!
10//! See [`Entity`] to learn more.
11//!
12//! [component]: crate::component::Component
13//!
14//! # Usage
15//!
16//! Operations involving entities and their components are performed either from a system by submitting commands,
17//! or from the outside (or from an exclusive system) by directly using [`World`] methods:
18//!
19//! |Operation|Command|Method|
20//! |:---:|:---:|:---:|
21//! |Spawn an entity with components|[`Commands::spawn`]|[`World::spawn`]|
22//! |Spawn an entity without components|[`Commands::spawn_empty`]|[`World::spawn_empty`]|
23//! |Despawn an entity|[`EntityCommands::despawn`]|[`World::despawn`]|
24//! |Insert a component, bundle, or tuple of components and bundles to an entity|[`EntityCommands::insert`]|[`EntityWorldMut::insert`]|
25//! |Remove a component, bundle, or tuple of components and bundles from an entity|[`EntityCommands::remove`]|[`EntityWorldMut::remove`]|
26//!
27//! [`World`]: crate::world::World
28//! [`Commands::spawn`]: crate::system::Commands::spawn
29//! [`Commands::spawn_empty`]: crate::system::Commands::spawn_empty
30//! [`EntityCommands::despawn`]: crate::system::EntityCommands::despawn
31//! [`EntityCommands::insert`]: crate::system::EntityCommands::insert
32//! [`EntityCommands::remove`]: crate::system::EntityCommands::remove
33//! [`World::spawn`]: crate::world::World::spawn
34//! [`World::spawn_empty`]: crate::world::World::spawn_empty
35//! [`World::despawn`]: crate::world::World::despawn
36//! [`EntityWorldMut::insert`]: crate::world::EntityWorldMut::insert
37//! [`EntityWorldMut::remove`]: crate::world::EntityWorldMut::remove
38mod map_entities;
39mod visit_entities;
40#[cfg(feature = "bevy_reflect")]
41use bevy_reflect::Reflect;
42#[cfg(all(feature = "bevy_reflect", feature = "serialize"))]
43use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
44pub use map_entities::*;
45pub use visit_entities::*;
46
47mod hash;
48pub use hash::*;
49
50use bevy_utils::tracing::warn;
51
52use crate::{
53 archetype::{ArchetypeId, ArchetypeRow},
54 identifier::{
55 error::IdentifierError,
56 kinds::IdKind,
57 masks::{IdentifierMask, HIGH_MASK},
58 Identifier,
59 },
60 storage::{SparseSetIndex, TableId, TableRow},
61};
62use core::{fmt, hash::Hash, mem, num::NonZero, sync::atomic::Ordering};
63#[cfg(feature = "serialize")]
64use serde::{Deserialize, Serialize};
65
66#[cfg(target_has_atomic = "64")]
67use core::sync::atomic::AtomicI64 as AtomicIdCursor;
68#[cfg(target_has_atomic = "64")]
69type IdCursor = i64;
70
71/// Most modern platforms support 64-bit atomics, but some less-common platforms
72/// do not. This fallback allows compilation using a 32-bit cursor instead, with
73/// the caveat that some conversions may fail (and panic) at runtime.
74#[cfg(not(target_has_atomic = "64"))]
75use core::sync::atomic::AtomicIsize as AtomicIdCursor;
76#[cfg(not(target_has_atomic = "64"))]
77type IdCursor = isize;
78
79/// Lightweight identifier of an [entity](crate::entity).
80///
81/// The identifier is implemented using a [generational index]: a combination of an index and a generation.
82/// This allows fast insertion after data removal in an array while minimizing loss of spatial locality.
83///
84/// These identifiers are only valid on the [`World`] it's sourced from. Attempting to use an `Entity` to
85/// fetch entity components or metadata from a different world will either fail or return unexpected results.
86///
87/// [generational index]: https://lucassardois.medium.com/generational-indices-guide-8e3c5f7fd594
88///
89/// # Stability warning
90/// For all intents and purposes, `Entity` should be treated as an opaque identifier. The internal bit
91/// representation is liable to change from release to release as are the behaviors or performance
92/// characteristics of any of its trait implementations (i.e. `Ord`, `Hash`, etc.). This means that changes in
93/// `Entity`'s representation, though made readable through various functions on the type, are not considered
94/// breaking changes under [SemVer].
95///
96/// In particular, directly serializing with `Serialize` and `Deserialize` make zero guarantee of long
97/// term wire format compatibility. Changes in behavior will cause serialized `Entity` values persisted
98/// to long term storage (i.e. disk, databases, etc.) will fail to deserialize upon being updated.
99///
100/// # Usage
101///
102/// This data type is returned by iterating a `Query` that has `Entity` as part of its query fetch type parameter ([learn more]).
103/// It can also be obtained by calling [`EntityCommands::id`] or [`EntityWorldMut::id`].
104///
105/// ```
106/// # use bevy_ecs::prelude::*;
107/// # #[derive(Component)]
108/// # struct SomeComponent;
109/// fn setup(mut commands: Commands) {
110/// // Calling `spawn` returns `EntityCommands`.
111/// let entity = commands.spawn(SomeComponent).id();
112/// }
113///
114/// fn exclusive_system(world: &mut World) {
115/// // Calling `spawn` returns `EntityWorldMut`.
116/// let entity = world.spawn(SomeComponent).id();
117/// }
118/// #
119/// # bevy_ecs::system::assert_is_system(setup);
120/// # bevy_ecs::system::assert_is_system(exclusive_system);
121/// ```
122///
123/// It can be used to refer to a specific entity to apply [`EntityCommands`], or to call [`Query::get`] (or similar methods) to access its components.
124///
125/// ```
126/// # use bevy_ecs::prelude::*;
127/// #
128/// # #[derive(Component)]
129/// # struct Expired;
130/// #
131/// fn dispose_expired_food(mut commands: Commands, query: Query<Entity, With<Expired>>) {
132/// for food_entity in &query {
133/// commands.entity(food_entity).despawn();
134/// }
135/// }
136/// #
137/// # bevy_ecs::system::assert_is_system(dispose_expired_food);
138/// ```
139///
140/// [learn more]: crate::system::Query#entity-id-access
141/// [`EntityCommands::id`]: crate::system::EntityCommands::id
142/// [`EntityWorldMut::id`]: crate::world::EntityWorldMut::id
143/// [`EntityCommands`]: crate::system::EntityCommands
144/// [`Query::get`]: crate::system::Query::get
145/// [`World`]: crate::world::World
146/// [SemVer]: https://semver.org/
147#[derive(Clone, Copy)]
148#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
149#[cfg_attr(feature = "bevy_reflect", reflect(opaque))]
150#[cfg_attr(feature = "bevy_reflect", reflect(Hash, PartialEq, Debug))]
151#[cfg_attr(
152 all(feature = "bevy_reflect", feature = "serialize"),
153 reflect(Serialize, Deserialize)
154)]
155// Alignment repr necessary to allow LLVM to better output
156// optimized codegen for `to_bits`, `PartialEq` and `Ord`.
157#[repr(C, align(8))]
158pub struct Entity {
159 // Do not reorder the fields here. The ordering is explicitly used by repr(C)
160 // to make this struct equivalent to a u64.
161 #[cfg(target_endian = "little")]
162 index: u32,
163 generation: NonZero<u32>,
164 #[cfg(target_endian = "big")]
165 index: u32,
166}
167
168// By not short-circuiting in comparisons, we get better codegen.
169// See <https://github.com/rust-lang/rust/issues/117800>
170impl PartialEq for Entity {
171 #[inline]
172 fn eq(&self, other: &Entity) -> bool {
173 // By using `to_bits`, the codegen can be optimized out even
174 // further potentially. Relies on the correct alignment/field
175 // order of `Entity`.
176 self.to_bits() == other.to_bits()
177 }
178}
179
180impl Eq for Entity {}
181
182// The derive macro codegen output is not optimal and can't be optimized as well
183// by the compiler. This impl resolves the issue of non-optimal codegen by relying
184// on comparing against the bit representation of `Entity` instead of comparing
185// the fields. The result is then LLVM is able to optimize the codegen for Entity
186// far beyond what the derive macro can.
187// See <https://github.com/rust-lang/rust/issues/106107>
188impl PartialOrd for Entity {
189 #[inline]
190 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
191 // Make use of our `Ord` impl to ensure optimal codegen output
192 Some(self.cmp(other))
193 }
194}
195
196// The derive macro codegen output is not optimal and can't be optimized as well
197// by the compiler. This impl resolves the issue of non-optimal codegen by relying
198// on comparing against the bit representation of `Entity` instead of comparing
199// the fields. The result is then LLVM is able to optimize the codegen for Entity
200// far beyond what the derive macro can.
201// See <https://github.com/rust-lang/rust/issues/106107>
202impl Ord for Entity {
203 #[inline]
204 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
205 // This will result in better codegen for ordering comparisons, plus
206 // avoids pitfalls with regards to macro codegen relying on property
207 // position when we want to compare against the bit representation.
208 self.to_bits().cmp(&other.to_bits())
209 }
210}
211
212impl Hash for Entity {
213 #[inline]
214 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
215 self.to_bits().hash(state);
216 }
217}
218
219pub(crate) enum AllocAtWithoutReplacement {
220 Exists(EntityLocation),
221 DidNotExist,
222 ExistsWithWrongGeneration,
223}
224
225impl Entity {
226 /// Construct an [`Entity`] from a raw `index` value and a non-zero `generation` value.
227 /// Ensure that the generation value is never greater than `0x7FFF_FFFF`.
228 #[inline(always)]
229 pub(crate) const fn from_raw_and_generation(index: u32, generation: NonZero<u32>) -> Entity {
230 debug_assert!(generation.get() <= HIGH_MASK);
231
232 Self { index, generation }
233 }
234
235 /// An entity ID with a placeholder value. This may or may not correspond to an actual entity,
236 /// and should be overwritten by a new value before being used.
237 ///
238 /// ## Examples
239 ///
240 /// Initializing a collection (e.g. `array` or `Vec`) with a known size:
241 ///
242 /// ```no_run
243 /// # use bevy_ecs::prelude::*;
244 /// // Create a new array of size 10 filled with invalid entity ids.
245 /// let mut entities: [Entity; 10] = [Entity::PLACEHOLDER; 10];
246 ///
247 /// // ... replace the entities with valid ones.
248 /// ```
249 ///
250 /// Deriving [`Reflect`] for a component that has an `Entity` field:
251 ///
252 /// ```no_run
253 /// # use bevy_ecs::{prelude::*, component::*};
254 /// # use bevy_reflect::Reflect;
255 /// #[derive(Reflect, Component)]
256 /// #[reflect(Component)]
257 /// pub struct MyStruct {
258 /// pub entity: Entity,
259 /// }
260 ///
261 /// impl FromWorld for MyStruct {
262 /// fn from_world(_world: &mut World) -> Self {
263 /// Self {
264 /// entity: Entity::PLACEHOLDER,
265 /// }
266 /// }
267 /// }
268 /// ```
269 pub const PLACEHOLDER: Self = Self::from_raw(u32::MAX);
270
271 /// Creates a new entity ID with the specified `index` and a generation of 1.
272 ///
273 /// # Note
274 ///
275 /// Spawning a specific `entity` value is __rarely the right choice__. Most apps should favor
276 /// [`Commands::spawn`](crate::system::Commands::spawn). This method should generally
277 /// only be used for sharing entities across apps, and only when they have a scheme
278 /// worked out to share an index space (which doesn't happen by default).
279 ///
280 /// In general, one should not try to synchronize the ECS by attempting to ensure that
281 /// `Entity` lines up between instances, but instead insert a secondary identifier as
282 /// a component.
283 #[inline(always)]
284 pub const fn from_raw(index: u32) -> Entity {
285 Self::from_raw_and_generation(index, NonZero::<u32>::MIN)
286 }
287
288 /// Convert to a form convenient for passing outside of rust.
289 ///
290 /// Only useful for identifying entities within the same instance of an application. Do not use
291 /// for serialization between runs.
292 ///
293 /// No particular structure is guaranteed for the returned bits.
294 #[inline(always)]
295 pub const fn to_bits(self) -> u64 {
296 IdentifierMask::pack_into_u64(self.index, self.generation.get())
297 }
298
299 /// Reconstruct an `Entity` previously destructured with [`Entity::to_bits`].
300 ///
301 /// Only useful when applied to results from `to_bits` in the same instance of an application.
302 ///
303 /// # Panics
304 ///
305 /// This method will likely panic if given `u64` values that did not come from [`Entity::to_bits`].
306 #[inline]
307 pub const fn from_bits(bits: u64) -> Self {
308 // Construct an Identifier initially to extract the kind from.
309 let id = Self::try_from_bits(bits);
310
311 match id {
312 Ok(entity) => entity,
313 Err(_) => panic!("Attempted to initialize invalid bits as an entity"),
314 }
315 }
316
317 /// Reconstruct an `Entity` previously destructured with [`Entity::to_bits`].
318 ///
319 /// Only useful when applied to results from `to_bits` in the same instance of an application.
320 ///
321 /// This method is the fallible counterpart to [`Entity::from_bits`].
322 #[inline(always)]
323 pub const fn try_from_bits(bits: u64) -> Result<Self, IdentifierError> {
324 if let Ok(id) = Identifier::try_from_bits(bits) {
325 let kind = id.kind() as u8;
326
327 if kind == (IdKind::Entity as u8) {
328 return Ok(Self {
329 index: id.low(),
330 generation: id.high(),
331 });
332 }
333 }
334
335 Err(IdentifierError::InvalidEntityId(bits))
336 }
337
338 /// Return a transiently unique identifier.
339 ///
340 /// No two simultaneously-live entities share the same index, but dead entities' indices may collide
341 /// with both live and dead entities. Useful for compactly representing entities within a
342 /// specific snapshot of the world, such as when serializing.
343 #[inline]
344 pub const fn index(self) -> u32 {
345 self.index
346 }
347
348 /// Returns the generation of this Entity's index. The generation is incremented each time an
349 /// entity with a given index is despawned. This serves as a "count" of the number of times a
350 /// given index has been reused (index, generation) pairs uniquely identify a given Entity.
351 #[inline]
352 pub const fn generation(self) -> u32 {
353 // Mask so not to expose any flags
354 IdentifierMask::extract_value_from_high(self.generation.get())
355 }
356}
357
358impl TryFrom<Identifier> for Entity {
359 type Error = IdentifierError;
360
361 #[inline]
362 fn try_from(value: Identifier) -> Result<Self, Self::Error> {
363 Self::try_from_bits(value.to_bits())
364 }
365}
366
367impl From<Entity> for Identifier {
368 #[inline]
369 fn from(value: Entity) -> Self {
370 Identifier::from_bits(value.to_bits())
371 }
372}
373
374#[cfg(feature = "serialize")]
375impl Serialize for Entity {
376 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
377 where
378 S: serde::Serializer,
379 {
380 serializer.serialize_u64(self.to_bits())
381 }
382}
383
384#[cfg(feature = "serialize")]
385impl<'de> Deserialize<'de> for Entity {
386 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
387 where
388 D: serde::Deserializer<'de>,
389 {
390 use serde::de::Error;
391 let id: u64 = Deserialize::deserialize(deserializer)?;
392 Entity::try_from_bits(id).map_err(D::Error::custom)
393 }
394}
395
396/// Outputs the full entity identifier, including the index, generation, and the raw bits.
397///
398/// This takes the format: `{index}v{generation}#{bits}`.
399///
400/// For [`Entity::PLACEHOLDER`], this outputs `PLACEHOLDER`.
401///
402/// # Usage
403///
404/// Prefer to use this format for debugging and logging purposes. Because the output contains
405/// the raw bits, it is easy to check it against serialized scene data.
406///
407/// Example serialized scene data:
408/// ```text
409/// (
410/// ...
411/// entities: {
412/// 4294967297: ( <--- Raw Bits
413/// components: {
414/// ...
415/// ),
416/// ...
417/// )
418/// ```
419impl fmt::Debug for Entity {
420 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
421 if self == &Self::PLACEHOLDER {
422 write!(f, "PLACEHOLDER")
423 } else {
424 write!(
425 f,
426 "{}v{}#{}",
427 self.index(),
428 self.generation(),
429 self.to_bits()
430 )
431 }
432 }
433}
434
435/// Outputs the short entity identifier, including the index and generation.
436///
437/// This takes the format: `{index}v{generation}`.
438///
439/// For [`Entity::PLACEHOLDER`], this outputs `PLACEHOLDER`.
440impl fmt::Display for Entity {
441 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
442 if self == &Self::PLACEHOLDER {
443 write!(f, "PLACEHOLDER")
444 } else {
445 write!(f, "{}v{}", self.index(), self.generation())
446 }
447 }
448}
449
450impl SparseSetIndex for Entity {
451 #[inline]
452 fn sparse_set_index(&self) -> usize {
453 self.index() as usize
454 }
455
456 #[inline]
457 fn get_sparse_set_index(value: usize) -> Self {
458 Entity::from_raw(value as u32)
459 }
460}
461
462/// An [`Iterator`] returning a sequence of [`Entity`] values from
463pub struct ReserveEntitiesIterator<'a> {
464 // Metas, so we can recover the current generation for anything in the freelist.
465 meta: &'a [EntityMeta],
466
467 // Reserved indices formerly in the freelist to hand out.
468 freelist_indices: core::slice::Iter<'a, u32>,
469
470 // New Entity indices to hand out, outside the range of meta.len().
471 new_indices: core::ops::Range<u32>,
472}
473
474impl<'a> Iterator for ReserveEntitiesIterator<'a> {
475 type Item = Entity;
476
477 fn next(&mut self) -> Option<Self::Item> {
478 self.freelist_indices
479 .next()
480 .map(|&index| {
481 Entity::from_raw_and_generation(index, self.meta[index as usize].generation)
482 })
483 .or_else(|| self.new_indices.next().map(Entity::from_raw))
484 }
485
486 fn size_hint(&self) -> (usize, Option<usize>) {
487 let len = self.freelist_indices.len() + self.new_indices.len();
488 (len, Some(len))
489 }
490}
491
492impl<'a> ExactSizeIterator for ReserveEntitiesIterator<'a> {}
493impl<'a> core::iter::FusedIterator for ReserveEntitiesIterator<'a> {}
494
495/// A [`World`]'s internal metadata store on all of its entities.
496///
497/// Contains metadata on:
498/// - The generation of every entity.
499/// - The alive/dead status of a particular entity. (i.e. "has entity 3 been despawned?")
500/// - The location of the entity's components in memory (via [`EntityLocation`])
501///
502/// [`World`]: crate::world::World
503#[derive(Debug)]
504pub struct Entities {
505 meta: Vec<EntityMeta>,
506
507 /// The `pending` and `free_cursor` fields describe three sets of Entity IDs
508 /// that have been freed or are in the process of being allocated:
509 ///
510 /// - The `freelist` IDs, previously freed by `free()`. These IDs are available to any of
511 /// [`alloc`], [`reserve_entity`] or [`reserve_entities`]. Allocation will always prefer
512 /// these over brand new IDs.
513 ///
514 /// - The `reserved` list of IDs that were once in the freelist, but got reserved by
515 /// [`reserve_entities`] or [`reserve_entity`]. They are now waiting for [`flush`] to make them
516 /// fully allocated.
517 ///
518 /// - The count of new IDs that do not yet exist in `self.meta`, but which we have handed out
519 /// and reserved. [`flush`] will allocate room for them in `self.meta`.
520 ///
521 /// The contents of `pending` look like this:
522 ///
523 /// ```txt
524 /// ----------------------------
525 /// | freelist | reserved |
526 /// ----------------------------
527 /// ^ ^
528 /// free_cursor pending.len()
529 /// ```
530 ///
531 /// As IDs are allocated, `free_cursor` is atomically decremented, moving
532 /// items from the freelist into the reserved list by sliding over the boundary.
533 ///
534 /// Once the freelist runs out, `free_cursor` starts going negative.
535 /// The more negative it is, the more IDs have been reserved starting exactly at
536 /// the end of `meta.len()`.
537 ///
538 /// This formulation allows us to reserve any number of IDs first from the freelist
539 /// and then from the new IDs, using only a single atomic subtract.
540 ///
541 /// Once [`flush`] is done, `free_cursor` will equal `pending.len()`.
542 ///
543 /// [`alloc`]: Entities::alloc
544 /// [`reserve_entity`]: Entities::reserve_entity
545 /// [`reserve_entities`]: Entities::reserve_entities
546 /// [`flush`]: Entities::flush
547 pending: Vec<u32>,
548 free_cursor: AtomicIdCursor,
549 /// Stores the number of free entities for [`len`](Entities::len)
550 len: u32,
551}
552
553impl Entities {
554 pub(crate) const fn new() -> Self {
555 Entities {
556 meta: Vec::new(),
557 pending: Vec::new(),
558 free_cursor: AtomicIdCursor::new(0),
559 len: 0,
560 }
561 }
562
563 /// Reserve entity IDs concurrently.
564 ///
565 /// Storage for entity generation and location is lazily allocated by calling [`flush`](Entities::flush).
566 #[allow(clippy::unnecessary_fallible_conversions)] // Because `IdCursor::try_from` may fail on 32-bit platforms.
567 pub fn reserve_entities(&self, count: u32) -> ReserveEntitiesIterator {
568 // Use one atomic subtract to grab a range of new IDs. The range might be
569 // entirely nonnegative, meaning all IDs come from the freelist, or entirely
570 // negative, meaning they are all new IDs to allocate, or a mix of both.
571 let range_end = self.free_cursor.fetch_sub(
572 IdCursor::try_from(count)
573 .expect("64-bit atomic operations are not supported on this platform."),
574 Ordering::Relaxed,
575 );
576 let range_start = range_end
577 - IdCursor::try_from(count)
578 .expect("64-bit atomic operations are not supported on this platform.");
579
580 let freelist_range = range_start.max(0) as usize..range_end.max(0) as usize;
581
582 let (new_id_start, new_id_end) = if range_start >= 0 {
583 // We satisfied all requests from the freelist.
584 (0, 0)
585 } else {
586 // We need to allocate some new Entity IDs outside of the range of self.meta.
587 //
588 // `range_start` covers some negative territory, e.g. `-3..6`.
589 // Since the nonnegative values `0..6` are handled by the freelist, that
590 // means we need to handle the negative range here.
591 //
592 // In this example, we truncate the end to 0, leaving us with `-3..0`.
593 // Then we negate these values to indicate how far beyond the end of `meta.end()`
594 // to go, yielding `meta.len()+0 .. meta.len()+3`.
595 let base = self.meta.len() as IdCursor;
596
597 let new_id_end = u32::try_from(base - range_start).expect("too many entities");
598
599 // `new_id_end` is in range, so no need to check `start`.
600 let new_id_start = (base - range_end.min(0)) as u32;
601
602 (new_id_start, new_id_end)
603 };
604
605 ReserveEntitiesIterator {
606 meta: &self.meta[..],
607 freelist_indices: self.pending[freelist_range].iter(),
608 new_indices: new_id_start..new_id_end,
609 }
610 }
611
612 /// Reserve one entity ID concurrently.
613 ///
614 /// Equivalent to `self.reserve_entities(1).next().unwrap()`, but more efficient.
615 pub fn reserve_entity(&self) -> Entity {
616 let n = self.free_cursor.fetch_sub(1, Ordering::Relaxed);
617 if n > 0 {
618 // Allocate from the freelist.
619 let index = self.pending[(n - 1) as usize];
620 Entity::from_raw_and_generation(index, self.meta[index as usize].generation)
621 } else {
622 // Grab a new ID, outside the range of `meta.len()`. `flush()` must
623 // eventually be called to make it valid.
624 //
625 // As `self.free_cursor` goes more and more negative, we return IDs farther
626 // and farther beyond `meta.len()`.
627 Entity::from_raw(
628 u32::try_from(self.meta.len() as IdCursor - n).expect("too many entities"),
629 )
630 }
631 }
632
633 /// Check that we do not have pending work requiring `flush()` to be called.
634 fn verify_flushed(&mut self) {
635 debug_assert!(
636 !self.needs_flush(),
637 "flush() needs to be called before this operation is legal"
638 );
639 }
640
641 /// Allocate an entity ID directly.
642 pub fn alloc(&mut self) -> Entity {
643 self.verify_flushed();
644 self.len += 1;
645 if let Some(index) = self.pending.pop() {
646 let new_free_cursor = self.pending.len() as IdCursor;
647 *self.free_cursor.get_mut() = new_free_cursor;
648 Entity::from_raw_and_generation(index, self.meta[index as usize].generation)
649 } else {
650 let index = u32::try_from(self.meta.len()).expect("too many entities");
651 self.meta.push(EntityMeta::EMPTY);
652 Entity::from_raw(index)
653 }
654 }
655
656 /// Allocate a specific entity ID, overwriting its generation.
657 ///
658 /// Returns the location of the entity currently using the given ID, if any. Location should be
659 /// written immediately.
660 pub fn alloc_at(&mut self, entity: Entity) -> Option<EntityLocation> {
661 self.verify_flushed();
662
663 let loc = if entity.index() as usize >= self.meta.len() {
664 self.pending
665 .extend((self.meta.len() as u32)..entity.index());
666 let new_free_cursor = self.pending.len() as IdCursor;
667 *self.free_cursor.get_mut() = new_free_cursor;
668 self.meta
669 .resize(entity.index() as usize + 1, EntityMeta::EMPTY);
670 self.len += 1;
671 None
672 } else if let Some(index) = self.pending.iter().position(|item| *item == entity.index()) {
673 self.pending.swap_remove(index);
674 let new_free_cursor = self.pending.len() as IdCursor;
675 *self.free_cursor.get_mut() = new_free_cursor;
676 self.len += 1;
677 None
678 } else {
679 Some(mem::replace(
680 &mut self.meta[entity.index() as usize].location,
681 EntityMeta::EMPTY.location,
682 ))
683 };
684
685 self.meta[entity.index() as usize].generation = entity.generation;
686
687 loc
688 }
689
690 /// Allocate a specific entity ID, overwriting its generation.
691 ///
692 /// Returns the location of the entity currently using the given ID, if any.
693 pub(crate) fn alloc_at_without_replacement(
694 &mut self,
695 entity: Entity,
696 ) -> AllocAtWithoutReplacement {
697 self.verify_flushed();
698
699 let result = if entity.index() as usize >= self.meta.len() {
700 self.pending
701 .extend((self.meta.len() as u32)..entity.index());
702 let new_free_cursor = self.pending.len() as IdCursor;
703 *self.free_cursor.get_mut() = new_free_cursor;
704 self.meta
705 .resize(entity.index() as usize + 1, EntityMeta::EMPTY);
706 self.len += 1;
707 AllocAtWithoutReplacement::DidNotExist
708 } else if let Some(index) = self.pending.iter().position(|item| *item == entity.index()) {
709 self.pending.swap_remove(index);
710 let new_free_cursor = self.pending.len() as IdCursor;
711 *self.free_cursor.get_mut() = new_free_cursor;
712 self.len += 1;
713 AllocAtWithoutReplacement::DidNotExist
714 } else {
715 let current_meta = &self.meta[entity.index() as usize];
716 if current_meta.location.archetype_id == ArchetypeId::INVALID {
717 AllocAtWithoutReplacement::DidNotExist
718 } else if current_meta.generation == entity.generation {
719 AllocAtWithoutReplacement::Exists(current_meta.location)
720 } else {
721 return AllocAtWithoutReplacement::ExistsWithWrongGeneration;
722 }
723 };
724
725 self.meta[entity.index() as usize].generation = entity.generation;
726 result
727 }
728
729 /// Destroy an entity, allowing it to be reused.
730 ///
731 /// Must not be called while reserved entities are awaiting `flush()`.
732 pub fn free(&mut self, entity: Entity) -> Option<EntityLocation> {
733 self.verify_flushed();
734
735 let meta = &mut self.meta[entity.index() as usize];
736 if meta.generation != entity.generation {
737 return None;
738 }
739
740 meta.generation = IdentifierMask::inc_masked_high_by(meta.generation, 1);
741
742 if meta.generation == NonZero::<u32>::MIN {
743 warn!(
744 "Entity({}) generation wrapped on Entities::free, aliasing may occur",
745 entity.index
746 );
747 }
748
749 let loc = mem::replace(&mut meta.location, EntityMeta::EMPTY.location);
750
751 self.pending.push(entity.index());
752
753 let new_free_cursor = self.pending.len() as IdCursor;
754 *self.free_cursor.get_mut() = new_free_cursor;
755 self.len -= 1;
756 Some(loc)
757 }
758
759 /// Ensure at least `n` allocations can succeed without reallocating.
760 #[allow(clippy::unnecessary_fallible_conversions)] // Because `IdCursor::try_from` may fail on 32-bit platforms.
761 pub fn reserve(&mut self, additional: u32) {
762 self.verify_flushed();
763
764 let freelist_size = *self.free_cursor.get_mut();
765 let shortfall = IdCursor::try_from(additional)
766 .expect("64-bit atomic operations are not supported on this platform.")
767 - freelist_size;
768 if shortfall > 0 {
769 self.meta.reserve(shortfall as usize);
770 }
771 }
772
773 /// Returns true if the [`Entities`] contains [`entity`](Entity).
774 // This will return false for entities which have been freed, even if
775 // not reallocated since the generation is incremented in `free`
776 pub fn contains(&self, entity: Entity) -> bool {
777 self.resolve_from_id(entity.index())
778 .map_or(false, |e| e.generation() == entity.generation())
779 }
780
781 /// Clears all [`Entity`] from the World.
782 pub fn clear(&mut self) {
783 self.meta.clear();
784 self.pending.clear();
785 *self.free_cursor.get_mut() = 0;
786 self.len = 0;
787 }
788
789 /// Returns the location of an [`Entity`].
790 /// Note: for pending entities, returns `Some(EntityLocation::INVALID)`.
791 #[inline]
792 pub fn get(&self, entity: Entity) -> Option<EntityLocation> {
793 if let Some(meta) = self.meta.get(entity.index() as usize) {
794 if meta.generation != entity.generation
795 || meta.location.archetype_id == ArchetypeId::INVALID
796 {
797 return None;
798 }
799 Some(meta.location)
800 } else {
801 None
802 }
803 }
804
805 /// Updates the location of an [`Entity`]. This must be called when moving the components of
806 /// the entity around in storage.
807 ///
808 /// # Safety
809 /// - `index` must be a valid entity index.
810 /// - `location` must be valid for the entity at `index` or immediately made valid afterwards
811 /// before handing control to unknown code.
812 #[inline]
813 pub(crate) unsafe fn set(&mut self, index: u32, location: EntityLocation) {
814 // SAFETY: Caller guarantees that `index` a valid entity index
815 let meta = unsafe { self.meta.get_unchecked_mut(index as usize) };
816 meta.location = location;
817 }
818
819 /// Increments the `generation` of a freed [`Entity`]. The next entity ID allocated with this
820 /// `index` will count `generation` starting from the prior `generation` + the specified
821 /// value + 1.
822 ///
823 /// Does nothing if no entity with this `index` has been allocated yet.
824 pub(crate) fn reserve_generations(&mut self, index: u32, generations: u32) -> bool {
825 if (index as usize) >= self.meta.len() {
826 return false;
827 }
828
829 let meta = &mut self.meta[index as usize];
830 if meta.location.archetype_id == ArchetypeId::INVALID {
831 meta.generation = IdentifierMask::inc_masked_high_by(meta.generation, generations);
832 true
833 } else {
834 false
835 }
836 }
837
838 /// Get the [`Entity`] with a given id, if it exists in this [`Entities`] collection
839 /// Returns `None` if this [`Entity`] is outside of the range of currently reserved Entities
840 ///
841 /// Note: This method may return [`Entities`](Entity) which are currently free
842 /// Note that [`contains`](Entities::contains) will correctly return false for freed
843 /// entities, since it checks the generation
844 pub fn resolve_from_id(&self, index: u32) -> Option<Entity> {
845 let idu = index as usize;
846 if let Some(&EntityMeta { generation, .. }) = self.meta.get(idu) {
847 Some(Entity::from_raw_and_generation(index, generation))
848 } else {
849 // `id` is outside of the meta list - check whether it is reserved but not yet flushed.
850 let free_cursor = self.free_cursor.load(Ordering::Relaxed);
851 // If this entity was manually created, then free_cursor might be positive
852 // Returning None handles that case correctly
853 let num_pending = usize::try_from(-free_cursor).ok()?;
854 (idu < self.meta.len() + num_pending).then_some(Entity::from_raw(index))
855 }
856 }
857
858 fn needs_flush(&mut self) -> bool {
859 *self.free_cursor.get_mut() != self.pending.len() as IdCursor
860 }
861
862 /// Allocates space for entities previously reserved with [`reserve_entity`](Entities::reserve_entity) or
863 /// [`reserve_entities`](Entities::reserve_entities), then initializes each one using the supplied function.
864 ///
865 /// # Safety
866 /// Flush _must_ set the entity location to the correct [`ArchetypeId`] for the given [`Entity`]
867 /// each time init is called. This _can_ be [`ArchetypeId::INVALID`], provided the [`Entity`]
868 /// has not been assigned to an [`Archetype`][crate::archetype::Archetype].
869 ///
870 /// Note: freshly-allocated entities (ones which don't come from the pending list) are guaranteed
871 /// to be initialized with the invalid archetype.
872 pub unsafe fn flush(&mut self, mut init: impl FnMut(Entity, &mut EntityLocation)) {
873 let free_cursor = self.free_cursor.get_mut();
874 let current_free_cursor = *free_cursor;
875
876 let new_free_cursor = if current_free_cursor >= 0 {
877 current_free_cursor as usize
878 } else {
879 let old_meta_len = self.meta.len();
880 let new_meta_len = old_meta_len + -current_free_cursor as usize;
881 self.meta.resize(new_meta_len, EntityMeta::EMPTY);
882 self.len += -current_free_cursor as u32;
883 for (index, meta) in self.meta.iter_mut().enumerate().skip(old_meta_len) {
884 init(
885 Entity::from_raw_and_generation(index as u32, meta.generation),
886 &mut meta.location,
887 );
888 }
889
890 *free_cursor = 0;
891 0
892 };
893
894 self.len += (self.pending.len() - new_free_cursor) as u32;
895 for index in self.pending.drain(new_free_cursor..) {
896 let meta = &mut self.meta[index as usize];
897 init(
898 Entity::from_raw_and_generation(index, meta.generation),
899 &mut meta.location,
900 );
901 }
902 }
903
904 /// Flushes all reserved entities to an "invalid" state. Attempting to retrieve them will return `None`
905 /// unless they are later populated with a valid archetype.
906 pub fn flush_as_invalid(&mut self) {
907 // SAFETY: as per `flush` safety docs, the archetype id can be set to [`ArchetypeId::INVALID`] if
908 // the [`Entity`] has not been assigned to an [`Archetype`][crate::archetype::Archetype], which is the case here
909 unsafe {
910 self.flush(|_entity, location| {
911 location.archetype_id = ArchetypeId::INVALID;
912 });
913 }
914 }
915
916 /// # Safety
917 ///
918 /// This function is safe if and only if the world this Entities is on has no entities.
919 pub unsafe fn flush_and_reserve_invalid_assuming_no_entities(&mut self, count: usize) {
920 let free_cursor = self.free_cursor.get_mut();
921 *free_cursor = 0;
922 self.meta.reserve(count);
923 // SAFETY: The EntityMeta struct only contains integers, and it is valid to have all bytes set to u8::MAX
924 unsafe {
925 self.meta.as_mut_ptr().write_bytes(u8::MAX, count);
926 }
927 // SAFETY: We have reserved `count` elements above and we have initialized values from index 0 to `count`.
928 unsafe {
929 self.meta.set_len(count);
930 }
931
932 self.len = count as u32;
933 }
934
935 /// The count of all entities in the [`World`] that have ever been allocated
936 /// including the entities that are currently freed.
937 ///
938 /// This does not include entities that have been reserved but have never been
939 /// allocated yet.
940 ///
941 /// [`World`]: crate::world::World
942 #[inline]
943 pub fn total_count(&self) -> usize {
944 self.meta.len()
945 }
946
947 /// The count of currently allocated entities.
948 #[inline]
949 pub fn len(&self) -> u32 {
950 self.len
951 }
952
953 /// Checks if any entity is currently active.
954 #[inline]
955 pub fn is_empty(&self) -> bool {
956 self.len == 0
957 }
958}
959
960// This type is repr(C) to ensure that the layout and values within it can be safe to fully fill
961// with u8::MAX, as required by [`Entities::flush_and_reserve_invalid_assuming_no_entities`].
962// Safety:
963// This type must not contain any pointers at any level, and be safe to fully fill with u8::MAX.
964/// Metadata for an [`Entity`].
965#[derive(Copy, Clone, Debug)]
966#[repr(C)]
967struct EntityMeta {
968 /// The current generation of the [`Entity`].
969 pub generation: NonZero<u32>,
970 /// The current location of the [`Entity`]
971 pub location: EntityLocation,
972}
973
974impl EntityMeta {
975 /// meta for **pending entity**
976 const EMPTY: EntityMeta = EntityMeta {
977 generation: NonZero::<u32>::MIN,
978 location: EntityLocation::INVALID,
979 };
980}
981
982// This type is repr(C) to ensure that the layout and values within it can be safe to fully fill
983// with u8::MAX, as required by [`Entities::flush_and_reserve_invalid_assuming_no_entities`].
984// SAFETY:
985// This type must not contain any pointers at any level, and be safe to fully fill with u8::MAX.
986/// A location of an entity in an archetype.
987#[derive(Copy, Clone, Debug, PartialEq)]
988#[repr(C)]
989pub struct EntityLocation {
990 /// The ID of the [`Archetype`] the [`Entity`] belongs to.
991 ///
992 /// [`Archetype`]: crate::archetype::Archetype
993 pub archetype_id: ArchetypeId,
994
995 /// The index of the [`Entity`] within its [`Archetype`].
996 ///
997 /// [`Archetype`]: crate::archetype::Archetype
998 pub archetype_row: ArchetypeRow,
999
1000 /// The ID of the [`Table`] the [`Entity`] belongs to.
1001 ///
1002 /// [`Table`]: crate::storage::Table
1003 pub table_id: TableId,
1004
1005 /// The index of the [`Entity`] within its [`Table`].
1006 ///
1007 /// [`Table`]: crate::storage::Table
1008 pub table_row: TableRow,
1009}
1010
1011impl EntityLocation {
1012 /// location for **pending entity** and **invalid entity**
1013 const INVALID: EntityLocation = EntityLocation {
1014 archetype_id: ArchetypeId::INVALID,
1015 archetype_row: ArchetypeRow::INVALID,
1016 table_id: TableId::INVALID,
1017 table_row: TableRow::INVALID,
1018 };
1019}
1020
1021#[cfg(test)]
1022mod tests {
1023 use super::*;
1024
1025 #[test]
1026 fn entity_niche_optimization() {
1027 assert_eq!(size_of::<Entity>(), size_of::<Option<Entity>>());
1028 }
1029
1030 #[test]
1031 fn entity_bits_roundtrip() {
1032 // Generation cannot be greater than 0x7FFF_FFFF else it will be an invalid Entity id
1033 let e =
1034 Entity::from_raw_and_generation(0xDEADBEEF, NonZero::<u32>::new(0x5AADF00D).unwrap());
1035 assert_eq!(Entity::from_bits(e.to_bits()), e);
1036 }
1037
1038 #[test]
1039 fn reserve_entity_len() {
1040 let mut e = Entities::new();
1041 e.reserve_entity();
1042 // SAFETY: entity_location is left invalid
1043 unsafe { e.flush(|_, _| {}) };
1044 assert_eq!(e.len(), 1);
1045 }
1046
1047 #[test]
1048 fn get_reserved_and_invalid() {
1049 let mut entities = Entities::new();
1050 let e = entities.reserve_entity();
1051 assert!(entities.contains(e));
1052 assert!(entities.get(e).is_none());
1053
1054 // SAFETY: entity_location is left invalid
1055 unsafe {
1056 entities.flush(|_entity, _location| {
1057 // do nothing ... leaving entity location invalid
1058 });
1059 };
1060
1061 assert!(entities.contains(e));
1062 assert!(entities.get(e).is_none());
1063 }
1064
1065 #[test]
1066 fn entity_const() {
1067 const C1: Entity = Entity::from_raw(42);
1068 assert_eq!(42, C1.index());
1069 assert_eq!(1, C1.generation());
1070
1071 const C2: Entity = Entity::from_bits(0x0000_00ff_0000_00cc);
1072 assert_eq!(0x0000_00cc, C2.index());
1073 assert_eq!(0x0000_00ff, C2.generation());
1074
1075 const C3: u32 = Entity::from_raw(33).index();
1076 assert_eq!(33, C3);
1077
1078 const C4: u32 = Entity::from_bits(0x00dd_00ff_0000_0000).generation();
1079 assert_eq!(0x00dd_00ff, C4);
1080 }
1081
1082 #[test]
1083 fn reserve_generations() {
1084 let mut entities = Entities::new();
1085 let entity = entities.alloc();
1086 entities.free(entity);
1087
1088 assert!(entities.reserve_generations(entity.index(), 1));
1089 }
1090
1091 #[test]
1092 fn reserve_generations_and_alloc() {
1093 const GENERATIONS: u32 = 10;
1094
1095 let mut entities = Entities::new();
1096 let entity = entities.alloc();
1097 entities.free(entity);
1098
1099 assert!(entities.reserve_generations(entity.index(), GENERATIONS));
1100
1101 // The very next entity allocated should be a further generation on the same index
1102 let next_entity = entities.alloc();
1103 assert_eq!(next_entity.index(), entity.index());
1104 assert!(next_entity.generation() > entity.generation() + GENERATIONS);
1105 }
1106
1107 #[test]
1108 #[allow(clippy::nonminimal_bool)] // This is intentionally testing `lt` and `ge` as separate functions.
1109 fn entity_comparison() {
1110 assert_eq!(
1111 Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap()),
1112 Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1113 );
1114 assert_ne!(
1115 Entity::from_raw_and_generation(123, NonZero::<u32>::new(789).unwrap()),
1116 Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1117 );
1118 assert_ne!(
1119 Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap()),
1120 Entity::from_raw_and_generation(123, NonZero::<u32>::new(789).unwrap())
1121 );
1122 assert_ne!(
1123 Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap()),
1124 Entity::from_raw_and_generation(456, NonZero::<u32>::new(123).unwrap())
1125 );
1126
1127 // ordering is by generation then by index
1128
1129 assert!(
1130 Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1131 >= Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1132 );
1133 assert!(
1134 Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1135 <= Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1136 );
1137 assert!(
1138 !(Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1139 < Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap()))
1140 );
1141 assert!(
1142 !(Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap())
1143 > Entity::from_raw_and_generation(123, NonZero::<u32>::new(456).unwrap()))
1144 );
1145
1146 assert!(
1147 Entity::from_raw_and_generation(9, NonZero::<u32>::new(1).unwrap())
1148 < Entity::from_raw_and_generation(1, NonZero::<u32>::new(9).unwrap())
1149 );
1150 assert!(
1151 Entity::from_raw_and_generation(1, NonZero::<u32>::new(9).unwrap())
1152 > Entity::from_raw_and_generation(9, NonZero::<u32>::new(1).unwrap())
1153 );
1154
1155 assert!(
1156 Entity::from_raw_and_generation(1, NonZero::<u32>::new(1).unwrap())
1157 < Entity::from_raw_and_generation(2, NonZero::<u32>::new(1).unwrap())
1158 );
1159 assert!(
1160 Entity::from_raw_and_generation(1, NonZero::<u32>::new(1).unwrap())
1161 <= Entity::from_raw_and_generation(2, NonZero::<u32>::new(1).unwrap())
1162 );
1163 assert!(
1164 Entity::from_raw_and_generation(2, NonZero::<u32>::new(2).unwrap())
1165 > Entity::from_raw_and_generation(1, NonZero::<u32>::new(2).unwrap())
1166 );
1167 assert!(
1168 Entity::from_raw_and_generation(2, NonZero::<u32>::new(2).unwrap())
1169 >= Entity::from_raw_and_generation(1, NonZero::<u32>::new(2).unwrap())
1170 );
1171 }
1172
1173 // Feel free to change this test if needed, but it seemed like an important
1174 // part of the best-case performance changes in PR#9903.
1175 #[test]
1176 fn entity_hash_keeps_similar_ids_together() {
1177 use core::hash::BuildHasher;
1178 let hash = EntityHash;
1179
1180 let first_id = 0xC0FFEE << 8;
1181 let first_hash = hash.hash_one(Entity::from_raw(first_id));
1182
1183 for i in 1..=255 {
1184 let id = first_id + i;
1185 let hash = hash.hash_one(Entity::from_raw(id));
1186 assert_eq!(hash.wrapping_sub(first_hash) as u32, i);
1187 }
1188 }
1189
1190 #[test]
1191 fn entity_hash_id_bitflip_affects_high_7_bits() {
1192 use core::hash::BuildHasher;
1193
1194 let hash = EntityHash;
1195
1196 let first_id = 0xC0FFEE;
1197 let first_hash = hash.hash_one(Entity::from_raw(first_id)) >> 57;
1198
1199 for bit in 0..u32::BITS {
1200 let id = first_id ^ (1 << bit);
1201 let hash = hash.hash_one(Entity::from_raw(id)) >> 57;
1202 assert_ne!(hash, first_hash);
1203 }
1204 }
1205
1206 #[test]
1207 fn entity_debug() {
1208 let entity = Entity::from_raw(42);
1209 let string = format!("{:?}", entity);
1210 assert_eq!(string, "42v1#4294967338");
1211
1212 let entity = Entity::PLACEHOLDER;
1213 let string = format!("{:?}", entity);
1214 assert_eq!(string, "PLACEHOLDER");
1215 }
1216
1217 #[test]
1218 fn entity_display() {
1219 let entity = Entity::from_raw(42);
1220 let string = format!("{}", entity);
1221 assert_eq!(string, "42v1");
1222
1223 let entity = Entity::PLACEHOLDER;
1224 let string = format!("{}", entity);
1225 assert_eq!(string, "PLACEHOLDER");
1226 }
1227}