various improvements per review

Co-Authored-By: Chris Russell <8494645+chescock@users.noreply.github.com>
This commit is contained in:
Elliott Pierce 2025-07-09 12:45:22 -04:00
parent 71675a3e75
commit fdf1b5526b

View File

@ -845,10 +845,12 @@ impl EntitiesAllocator {
} }
pub(crate) fn alloc_many(&self, count: u32) -> AllocEntitiesIterator<'_> { pub(crate) fn alloc_many(&self, count: u32) -> AllocEntitiesIterator<'_> {
let current_len = self let current_len = self.free_len.fetch_sub(count, Ordering::Relaxed);
.free_len let current_len = if current_len < self.free.len() as u32 {
.fetch_sub(count, Ordering::Relaxed) current_len
.min(self.free.len() as u32); } else {
0
};
let start = current_len.saturating_sub(count); let start = current_len.saturating_sub(count);
let reuse = (start as usize)..(current_len as usize); let reuse = (start as usize)..(current_len as usize);
let still_need = count - reuse.len() as u32; let still_need = count - reuse.len() as u32;
@ -926,45 +928,23 @@ impl Entities {
&self, &self,
entity: Entity, entity: Entity,
) -> Result<EntityLocation, ConstructedEntityDoesNotExistError> { ) -> Result<EntityLocation, ConstructedEntityDoesNotExistError> {
match self.meta.get(entity.index() as usize) { let meta = self.meta.get(entity.index() as usize);
Some(meta) => { let meta = meta.unwrap_or(&EntityMeta::FRESH);
if meta.generation != entity.generation { if entity.generation() != meta.generation {
Err(ConstructedEntityDoesNotExistError::DidNotExist( return Err(ConstructedEntityDoesNotExistError::DidNotExist(
EntityDoesNotExistError { EntityDoesNotExistError {
entity, entity,
current_generation: meta.generation, current_generation: meta.generation,
}, },
)) ));
} else { };
match meta.location { meta.location
Some(location) => Ok(location), .ok_or(ConstructedEntityDoesNotExistError::WasNotConstructed(
None => Err(ConstructedEntityDoesNotExistError::WasNotConstructed( EntityNotConstructedError {
EntityNotConstructedError { entity,
entity, location: meta.spawned_or_despawned.by,
location: meta.spawned_or_despawned.by.map(Some), },
}, ))
)),
}
}
}
None => {
if entity.generation() == EntityGeneration::FIRST {
Err(ConstructedEntityDoesNotExistError::WasNotConstructed(
EntityNotConstructedError {
entity,
location: MaybeLocation::new(None),
},
))
} else {
Err(ConstructedEntityDoesNotExistError::DidNotExist(
EntityDoesNotExistError {
entity,
current_generation: EntityGeneration::FIRST,
},
))
}
}
}
} }
/// Returns the [`EntityIdLocation`] of an [`Entity`] if it exists. /// Returns the [`EntityIdLocation`] of an [`Entity`] if it exists.
@ -972,27 +952,10 @@ impl Entities {
/// See the module docs for a full explanation of these ids, entity life cycles, and the meaning of this result. /// See the module docs for a full explanation of these ids, entity life cycles, and the meaning of this result.
#[inline] #[inline]
pub fn get(&self, entity: Entity) -> Result<EntityIdLocation, EntityDoesNotExistError> { pub fn get(&self, entity: Entity) -> Result<EntityIdLocation, EntityDoesNotExistError> {
match self.meta.get(entity.index() as usize) { match self.get_constructed(entity) {
Some(meta) => { Ok(location) => Ok(Some(location)),
if meta.generation == entity.generation { Err(ConstructedEntityDoesNotExistError::WasNotConstructed { .. }) => Ok(None),
Ok(meta.location) Err(ConstructedEntityDoesNotExistError::DidNotExist(err)) => Err(err),
} else {
Err(EntityDoesNotExistError {
entity,
current_generation: meta.generation,
})
}
}
None => {
if entity.generation() == EntityGeneration::FIRST {
Ok(None)
} else {
Err(EntityDoesNotExistError {
entity,
current_generation: EntityGeneration::FIRST,
})
}
}
} }
} }
@ -1250,18 +1213,14 @@ pub struct EntityNotConstructedError {
/// The entity's ID. /// The entity's ID.
pub entity: Entity, pub entity: Entity,
/// The location of what last destructed the entity. /// The location of what last destructed the entity.
pub location: MaybeLocation<Option<&'static Location<'static>>>, pub location: MaybeLocation<&'static Location<'static>>,
} }
impl fmt::Display for EntityNotConstructedError { impl fmt::Display for EntityNotConstructedError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let entity = self.entity; let entity = self.entity;
match self.location.into_option() { match self.location.into_option() {
Some(Some(location)) => write!(f, "The entity with ID {entity} is not constructed; its row was last destructed by {location}."), Some(location) => write!(f, "The entity with ID {entity} is not constructed; its row was last destructed by {location}."),
Some(None) => write!(
f,
"The entity with ID {entity} is not constructed; its row has never been constructed."
),
None => write!( None => write!(
f, f,
"The entity with ID {entity} is not constructed; enable `track_location` feature for more details." "The entity with ID {entity} is not constructed; enable `track_location` feature for more details."
@ -1623,4 +1582,28 @@ mod tests {
let string = format!("{entity}"); let string = format!("{entity}");
assert_eq!(string, "PLACEHOLDER"); assert_eq!(string, "PLACEHOLDER");
} }
#[test]
fn allocator() {
let mut allocator = EntitiesAllocator::default();
let mut entities = allocator.alloc_many(2048).collect::<Vec<_>>();
for _ in 0..2048 {
entities.push(allocator.alloc());
}
let pre_len = entities.len();
entities.sort();
entities.dedup();
assert_eq!(pre_len, entities.len());
for e in entities.drain(..) {
allocator.free(e);
}
entities.extend(allocator.alloc_many(5000));
let pre_len = entities.len();
entities.sort();
entities.dedup();
assert_eq!(pre_len, entities.len());
}
} }