EntityPool.ixx File
Object pool for efficient Entity management and recycling. More...
Included Headers
#include <memory>
#include <unordered_map>
#include <vector>
#include <cassert>
#include <limits>
#include <span>
#include <cstddef>
#include <helios.ecs.types>
#include <helios.ecs.types.EntityHandle>
#include <helios.engine.util.Guid>
Namespaces Index
| namespace | helios |
| namespace | engine |
| namespace | runtime |
| namespace | pooling |
Classes Index
| class | EntityPool<THandle> |
|
Object pool for efficient Entity lifecycle management. More... | |
Description
Object pool for efficient Entity management and recycling.
Provides a memory-efficient pooling mechanism for frequently spawned and despawned Entities, such as projectiles, particles, or enemies. Pre-allocates objects at construction time and reuses them to avoid runtime allocation overhead.
File Listing
The file content with the documentation metadata removed is:
26export namespace helios::engine::runtime::pooling {
46 class EntityPool {
56 std::vector<size_t> activeIndex_;
63 std::vector<size_t> versionIndex_;
68 std::vector<THandle> activeEntities_;
73 std::vector<THandle> inactiveEntities_;
83 helios::ecs::types::EntityId minEntityId_ = std::numeric_limits<helios::ecs::types::EntityId>::max();
88 helios::ecs::types::EntityId maxEntityId_ = std::numeric_limits<helios::ecs::types::EntityId>::lowest();
98 const helios::engine::util::Guid guid_;
116 explicit EntityPool(
117 size_t poolSize
121 activeEntities_.reserve(poolSize);
122 inactiveEntities_.reserve(poolSize);
132 return guid_;
141 return poolSize_;
155 [[nodiscard]] bool acquire(THandle& entityHandle) {
157 if (inactiveEntities_.empty()) {
161 entityHandle = inactiveEntities_.back();
162 inactiveEntities_.pop_back();
165 auto idx = entityHandle.entityId - delta_;
167 if (activeIndex_.size() <= idx) {
168 activeIndex_.resize(idx + 1, helios::ecs::types::EntityTombstone);
169 versionIndex_.resize(idx + 1, helios::ecs::types::EntityTombstone);
172 activeIndex_[idx] = activeEntities_.size();
173 versionIndex_[idx] = entityHandle.versionId;
175 activeEntities_.push_back(entityHandle);
186 return locked_;
196 locked_ = true;
197 delta_ = minEntityId_;
198 activeIndex_.resize(maxEntityId_ - delta_ + 1, helios::ecs::types::EntityTombstone);
199 versionIndex_.resize(maxEntityId_ - delta_ + 1, helios::ecs::types::EntityTombstone);
212 bool addInactive(const THandle entityHandle) {
216 assert(entityHandle.isValid() && "Unexpected invalid entityHandle");
218 const size_t used = (activeCount() + inactiveCount());
220 minEntityId_ = std::min(minEntityId_, entityHandle.entityId);
221 maxEntityId_ = std::max(maxEntityId_, entityHandle.entityId);
225 inactiveEntities_.push_back(entityHandle);
245 bool release(const THandle entityHandle) {
247 assert(entityHandle.isValid() && "Unexpected invalid entityHandle");
249 assert(entityHandle.entityId >= delta_ && "Unexpected entityHandle");
251 const auto sparseIdx = entityHandle.entityId - delta_;
253 assert(sparseIdx < activeIndex_.size() && "Unexpected sparse index");
255 const auto denseIndex = activeIndex_[sparseIdx];
256 if (denseIndex == helios::ecs::types::EntityTombstone) {
260 assert(versionIndex_[sparseIdx] == entityHandle.versionId && "Version mismatch");
262 auto lastEntityHandle = activeEntities_.back();
264 if (denseIndex != activeEntities_.size() - 1) {
269 activeIndex_[lastEntityHandle.entityId-delta_] = denseIndex;
270 versionIndex_[lastEntityHandle.entityId-delta_] = lastEntityHandle.versionId;
276 activeEntities_.pop_back();
280 activeIndex_[sparseIdx] = helios::ecs::types::EntityTombstone;
281 versionIndex_[sparseIdx] = helios::ecs::types::EntityTombstone;
283 inactiveEntities_.push_back(entityHandle);
299 bool releaseAndRemove(const THandle entityHandle) {
301 assert(entityHandle.isValid() && "Unexpected invalid entityHandle");
303 const auto sparseIdx = entityHandle.entityId - delta_;
305 assert(sparseIdx < activeIndex_.size() && "Unexpected sparse index");
307 const auto denseIndex = activeIndex_[sparseIdx];
309 if (denseIndex == helios::ecs::types::EntityTombstone) {
313 assert(versionIndex_[sparseIdx] == entityHandle.versionId && "Version mismatch");
315 if (denseIndex != activeEntities_.size() - 1) {
316 const auto lastEntityHandle = activeEntities_.back();
317 activeIndex_[lastEntityHandle.entityId - delta_] = denseIndex;
318 versionIndex_[lastEntityHandle.entityId - delta_] = lastEntityHandle.versionId;
322 activeEntities_.pop_back();
324 activeIndex_[sparseIdx] = helios::ecs::types::EntityTombstone;
325 versionIndex_[sparseIdx] = helios::ecs::types::EntityTombstone;
337 [[nodiscard]] size_t activeCount() const noexcept {
338 return activeEntities_.size();
346 [[nodiscard]] size_t inactiveCount() const noexcept {
347 return inactiveEntities_.size();
355 std::span<THandle> inactiveEntities() {
356 return inactiveEntities_;
364 std::span<THandle> activeEntities() {
365 return activeEntities_;
Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.9.8.