Address Entities::len inconsistency (#18190)

# Objective

I was recently exploreing `Entities` and stumbled on something strange.
`Entities::len` (the field) has the comment `Stores the number of free
entities for [`len`](Entities::len)`, refering to the method. But that
method says `The count of currently allocated entities.` Looking at the
code, the field's comment is wrong, and the public `len()` is correct.
Phew!

## Solution

So, I was just going to fix the comment, so it didn't confuse anyone
else, but as it turns out, we can just remove the field entirely. As a
bonus, this saves some book keeping work too. We can just calculate it
on the fly.

Also, add additional length methods and documentation for completeness.
These new length methods might be useful debug tools in the future.

---------

Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
This commit is contained in:
Eagster 2025-03-10 17:51:01 -04:00 committed by GitHub
parent 21f003f13f
commit 65a9e6fd9f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -582,8 +582,6 @@ pub struct Entities {
/// [`flush`]: Entities::flush
pending: Vec<u32>,
free_cursor: AtomicIdCursor,
/// Stores the number of free entities for [`len`](Entities::len)
len: u32,
}
impl Entities {
@ -592,7 +590,6 @@ impl Entities {
meta: Vec::new(),
pending: Vec::new(),
free_cursor: AtomicIdCursor::new(0),
len: 0,
}
}
@ -684,7 +681,6 @@ impl Entities {
/// Allocate an entity ID directly.
pub fn alloc(&mut self) -> Entity {
self.verify_flushed();
self.len += 1;
if let Some(index) = self.pending.pop() {
let new_free_cursor = self.pending.len() as IdCursor;
*self.free_cursor.get_mut() = new_free_cursor;
@ -713,13 +709,11 @@ impl Entities {
*self.free_cursor.get_mut() = new_free_cursor;
self.meta
.resize(entity.index() as usize + 1, EntityMeta::EMPTY);
self.len += 1;
None
} else if let Some(index) = self.pending.iter().position(|item| *item == entity.index()) {
self.pending.swap_remove(index);
let new_free_cursor = self.pending.len() as IdCursor;
*self.free_cursor.get_mut() = new_free_cursor;
self.len += 1;
None
} else {
Some(mem::replace(
@ -756,13 +750,11 @@ impl Entities {
*self.free_cursor.get_mut() = new_free_cursor;
self.meta
.resize(entity.index() as usize + 1, EntityMeta::EMPTY);
self.len += 1;
AllocAtWithoutReplacement::DidNotExist
} else if let Some(index) = self.pending.iter().position(|item| *item == entity.index()) {
self.pending.swap_remove(index);
let new_free_cursor = self.pending.len() as IdCursor;
*self.free_cursor.get_mut() = new_free_cursor;
self.len += 1;
AllocAtWithoutReplacement::DidNotExist
} else {
let current_meta = &self.meta[entity.index() as usize];
@ -805,7 +797,6 @@ impl Entities {
let new_free_cursor = self.pending.len() as IdCursor;
*self.free_cursor.get_mut() = new_free_cursor;
self.len -= 1;
Some(loc)
}
@ -843,7 +834,6 @@ impl Entities {
self.meta.clear();
self.pending.clear();
*self.free_cursor.get_mut() = 0;
self.len = 0;
}
/// Returns the location of an [`Entity`].
@ -939,7 +929,6 @@ impl Entities {
let old_meta_len = self.meta.len();
let new_meta_len = old_meta_len + -current_free_cursor as usize;
self.meta.resize(new_meta_len, EntityMeta::EMPTY);
self.len += -current_free_cursor as u32;
for (index, meta) in self.meta.iter_mut().enumerate().skip(old_meta_len) {
init(
Entity::from_raw_and_generation(index as u32, meta.generation),
@ -951,7 +940,6 @@ impl Entities {
0
};
self.len += (self.pending.len() - new_free_cursor) as u32;
for index in self.pending.drain(new_free_cursor..) {
let meta = &mut self.meta[index as usize];
init(
@ -985,16 +973,35 @@ impl Entities {
self.meta.len()
}
/// The count of all entities in the [`World`] that are used,
/// including both those allocated and those reserved, but not those freed.
///
/// [`World`]: crate::world::World
#[inline]
pub fn used_count(&self) -> usize {
(self.meta.len() as isize - self.free_cursor.load(Ordering::Relaxed) as isize) as usize
}
/// The count of all entities in the [`World`] that have ever been allocated or reserved, including those that are freed.
/// This is the value that [`Self::total_count()`] would return if [`Self::flush()`] were called right now.
///
/// [`World`]: crate::world::World
#[inline]
pub fn total_prospective_count(&self) -> usize {
self.meta.len() + (-self.free_cursor.load(Ordering::Relaxed)).min(0) as usize
}
/// The count of currently allocated entities.
#[inline]
pub fn len(&self) -> u32 {
self.len
// `pending`, by definition, can't be bigger than `meta`.
(self.meta.len() - self.pending.len()) as u32
}
/// Checks if any entity is currently active.
#[inline]
pub fn is_empty(&self) -> bool {
self.len == 0
self.len() == 0
}
/// Sets the source code location from which this entity has last been spawned