@@ -31,18 +31,20 @@ namespace cage
3131 class EntityManagerImpl : public EntityManager
3232 {
3333 public:
34+ const EntityManagerCreateConfig config;
3435 Holder<MemoryArena> arena;
3536 std::vector<Holder<ComponentImpl>> components;
3637 std::vector<EntityComponent *> componentsByTypes;
3738 ankerl::unordered_dense::map<uint32, Entity *> namedEntities;
3839 FlatBag<Entity *> allEntities;
3940 uint32 generateId = 0 ;
4041 uint32 entSize = 0 ;
41- bool linearArena = false ;
42+
43+ EntityManagerImpl (const EntityManagerCreateConfig &config) : config(config) {}
4244
4345 ~EntityManagerImpl ()
4446 {
45- destroy ();
47+ purge ();
4648 components.clear ();
4749 }
4850
@@ -66,12 +68,19 @@ namespace cage
6668 }
6769 catch (...)
6870 {
69- arena->deallocate (ptr);
71+ if (!config.linearAllocators )
72+ arena->deallocate (ptr);
7073 throw ;
7174 }
7275 }
7376
74- void desEnt (EntityImpl *e) { arena->destroy <EntityImpl>(e); }
77+ void desEnt (EntityImpl *e)
78+ {
79+ if (config.linearAllocators )
80+ e->~EntityImpl ();
81+ else
82+ arena->destroy <EntityImpl>(e);
83+ }
7584 };
7685
7786 class ComponentImpl : public EntityComponent
@@ -91,12 +100,19 @@ namespace cage
91100 CAGE_ASSERT (typeSize > 0 );
92101 prototype = systemMemory ().createBuffer (typeSize, typeAlignment).cast <void >();
93102 detail::memcpy (+prototype, prototype_, typeSize);
94- arena = newMemoryAllocatorPool ({ std::max (typeSize, uint32 (sizeof (uintPtr))), typeAlignment });
103+ if (manager->config .linearAllocators )
104+ arena = newMemoryAllocatorLinear ({});
105+ else
106+ arena = newMemoryAllocatorPool ({ std::max (typeSize, uint32 (sizeof (uintPtr))), typeAlignment });
95107 }
96108
97109 void *newVal () { return arena->allocate (typeSize, typeAlignment); }
98110
99- void desVal (void *v) { arena->deallocate (v); }
111+ void desVal (void *v)
112+ {
113+ if (!manager->config .linearAllocators )
114+ arena->deallocate (v);
115+ }
100116 };
101117
102118 EntityImpl::EntityImpl (EntityManagerImpl *manager, uint32 id) : manager(manager), id(id)
@@ -244,13 +260,11 @@ namespace cage
244260 void EntityManager::destroy ()
245261 {
246262 EntityManagerImpl *impl = (EntityManagerImpl *)this ;
247- if (impl->linearArena )
248- impl->purge ();
249- else
250- {
251- while (!impl->allEntities .empty ())
252- impl->allEntities .unsafeData ().back ()->destroy ();
253- }
263+ // first call all callbacks
264+ while (!impl->allEntities .empty ())
265+ impl->allEntities .unsafeData ().back ()->destroy ();
266+ // second free the memory
267+ impl->purge ();
254268 }
255269
256270 void EntityManager::purge ()
@@ -285,7 +299,10 @@ namespace cage
285299 ComponentImpl *c = +h;
286300 impl->components .push_back (std::move (h));
287301 impl->entSize = sizeof (EntityImpl) + impl->components .size () * sizeof (void *);
288- impl->arena = newMemoryAllocatorPool ({ impl->entSize , alignof (EntityImpl) });
302+ if (impl->config .linearAllocators )
303+ impl->arena = newMemoryAllocatorLinear ({});
304+ else
305+ impl->arena = newMemoryAllocatorPool ({ impl->entSize , alignof (EntityImpl) });
289306 return c;
290307 }
291308
@@ -294,9 +311,9 @@ namespace cage
294311 return defineComponent_ (source->typeIndex (), +((ComponentImpl *)source)->prototype );
295312 }
296313
297- Holder<EntityManager> newEntityManager ()
314+ Holder<EntityManager> newEntityManager (const EntityManagerCreateConfig &config )
298315 {
299- return systemMemory ().createImpl <EntityManager, EntityManagerImpl>();
316+ return systemMemory ().createImpl <EntityManager, EntityManagerImpl>(config );
300317 }
301318
302319 EntityManager *EntityComponent::manager () const
@@ -437,7 +454,6 @@ namespace cage
437454 const EntityManagerImpl *src = (const EntityManagerImpl *)config.source ;
438455 EntityManagerImpl *dst = (EntityManagerImpl *)config.destination ;
439456
440- CAGE_ASSERT (!config.linearAllocator || config.purge ); // linear arena must purge
441457 if (config.purge )
442458 dst->purge ();
443459 else
@@ -446,19 +462,6 @@ namespace cage
446462 // must define components before changing the allocators
447463 const auto mp = componnentMapping (config);
448464
449- CAGE_ASSERT (!dst->linearArena || config.linearAllocator ); // cannot take back
450- if (config.linearAllocator && !dst->linearArena )
451- {
452- dst->linearArena = true ;
453- for (const auto &it : dst->components )
454- {
455- it->arena .clear ();
456- it->arena = newMemoryAllocatorLinear ({});
457- }
458- dst->arena .clear ();
459- dst->arena = newMemoryAllocatorLinear ({});
460- }
461-
462465 ankerl::unordered_dense::map<Entity *, EntityImpl *> ents; // old -> new
463466 ents.reserve (src->count ());
464467 dst->allEntities .unsafeData ().reserve (src->allEntities .size ());
@@ -471,7 +474,7 @@ namespace cage
471474 dst->allEntities .unsafeData ().push_back (n);
472475 ents[se] = n;
473476 }
474- if (! config.linearAllocator )
477+ if (config.rebuildIndices )
475478 dst->allEntities .unsafeRebuildIndex ();
476479 for (Entity *e : dst->allEntities )
477480 {
@@ -491,7 +494,7 @@ namespace cage
491494 detail::memcpy (de->comp (di) = dc->newVal (), se->comp (si), sz);
492495 dc->componentEntities .unsafeData ().push_back (de);
493496 }
494- if (! config.linearAllocator )
497+ if (config.rebuildIndices )
495498 dc->componentEntities .unsafeRebuildIndex ();
496499 }
497500 }
0 commit comments