Skip to content

Commit

Permalink
let Archetype only store chunk pool (not EntityMngr)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ubpa committed Sep 16, 2020
1 parent 77cba04 commit ea14b33
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 49 deletions.
9 changes: 3 additions & 6 deletions include/UECS/EntityMngr.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
#include "detail/Job.h"
#include "EntityQuery.h"

#include <UContainer/Pool.h>

#include <memory>

namespace Ubpa::UECS {
class World;

Expand All @@ -28,8 +24,9 @@ namespace Ubpa::UECS {
// - when free entries is empty, use new entity entry (version is 0)
class EntityMngr {
public:
EntityMngr(World* world) : world{ world } {}
EntityMngr(World* world) : world{ world }, sharedChunkPool{ std::make_unique<Pool<Chunk>>() } {}
EntityMngr(const EntityMngr& em);
~EntityMngr();

// same world
void Swap(EntityMngr& rhs) noexcept;
Expand Down Expand Up @@ -94,7 +91,6 @@ namespace Ubpa::UECS {
void Accept(IListener* listener) const;

private:
Pool<Chunk> sharedChunkPool; // destruct finally
World* world;

friend class World;
Expand Down Expand Up @@ -134,6 +130,7 @@ namespace Ubpa::UECS {
size_t RequestEntityFreeEntry();
void RecycleEntityEntry(Entity);

std::unique_ptr<Pool<Chunk>> sharedChunkPool;
std::unordered_map<CmptTypeSet, std::unique_ptr<Archetype>> ts2a; // archetype's CmptTypeSet to archetype
};
}
Expand Down
2 changes: 1 addition & 1 deletion include/UECS/RTDCmptTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <functional>

namespace Ubpa::UECS {
// run-time dynamic component traits, singleton
// run-time dynamic component traits
// size (> 0) is neccessary
// optional
// - alignment: alignof(std::max_align_t) as default, 8 / 16 in most cases
Expand Down
22 changes: 12 additions & 10 deletions include/UECS/detail/Archetype.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "CmptTypeSet.h"
#include "Chunk.h"

#include <UContainer/Pool.h>

#include <UTemplate/Typelist.h>
#include <UTemplate/TypeID.h>

Expand All @@ -20,23 +22,26 @@ namespace Ubpa::UECS {
// type of Entity + Components is Archetype's type
class Archetype {
public:
Archetype(Pool<Chunk>* chunkPool) : chunkPool{ chunkPool } {}

// argument TypeList<Cmpts...> is for type deduction
// auto add Entity
template<typename... Cmpts>
Archetype(EntityMngr*, TypeList<Cmpts...>);
Archetype(Pool<Chunk>* chunkPool, TypeList<Cmpts...>);

// copy
Archetype(EntityMngr*, const Archetype&);
Archetype(Pool<Chunk>* chunkPool, const Archetype&);
Archetype(const Archetype&) = delete;

~Archetype();

// auto add Entity, use RTDCmptTraits
static Archetype* New(EntityMngr*, const CmptType* types, size_t num);
// auto add Entity
static Archetype* New(RTDCmptTraits&, Pool<Chunk>* chunkPool, const CmptType* types, size_t num);

// auto add Entity
template<typename... Cmpts>
static Archetype* Add(const Archetype* from);
static Archetype* Add(const Archetype* from, const CmptType* types, size_t num);
static Archetype* Add(RTDCmptTraits&, const Archetype* from, const CmptType* types, size_t num);

// auto add Entity
static Archetype* Remove(const Archetype* from, const CmptType* types, size_t num);
Expand Down Expand Up @@ -68,8 +73,7 @@ namespace Ubpa::UECS {
template<typename... Cmpts>
std::tuple<size_t, std::tuple<Cmpts*...>> Create(Entity);

// use RTDCmptTraits's default constructor
size_t Create(Entity);
size_t Create(RTDCmptTraits&, Entity);

// return index in archetype
size_t Instantiate(Entity, size_t srcIdx);
Expand All @@ -95,8 +99,6 @@ namespace Ubpa::UECS {
static CmptTypeSet GenCmptTypeSet();

private:
Archetype(EntityMngr* entityMngr) : entityMngr{ entityMngr } {}

// set type2alignment
// call after setting type2size and type2offset
void SetLayout();
Expand All @@ -105,13 +107,13 @@ namespace Ubpa::UECS {
static bool NotContainEntity(const CmptType* types, size_t num) noexcept;

friend class EntityMngr;
EntityMngr* entityMngr;

CmptTypeSet types; // Entity + Components
RTSCmptTraits cmptTraits;
std::unordered_map<CmptType, size_t> type2offset; // CmptType to offset in chunk (include Entity)

size_t chunkCapacity{ size_t_invalid };
Pool<Chunk>* chunkPool;
std::vector<Chunk*> chunks;

size_t entityNum{ 0 }; // number of entities
Expand Down
7 changes: 3 additions & 4 deletions include/UECS/detail/Archetype.inl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

namespace Ubpa::UECS {
template<typename... Cmpts>
Archetype::Archetype(EntityMngr* entityMngr, TypeList<Cmpts...>)
:
entityMngr{ entityMngr },
Archetype::Archetype(Pool<Chunk>* chunkPool, TypeList<Cmpts...>)
: chunkPool{ chunkPool },
types(GenCmptTypeSet<Cmpts...>())
{
static_assert(IsSet_v<TypeList<Entity, Cmpts...>>,
Expand All @@ -23,7 +22,7 @@ namespace Ubpa::UECS {
"<Cmpts>... must be different");
assert(!(from->types.Contains(CmptType::Of<Cmpts>) &&...));

Archetype* rst = new Archetype{ from->entityMngr };
Archetype* rst = new Archetype{ from->chunkPool };

rst->types = from->types;
(rst->types.data.insert(CmptType::Of<Cmpts>), ...);
Expand Down
2 changes: 1 addition & 1 deletion include/UECS/detail/EntityMngr.inl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Ubpa::UECS {
if(target != ts2a.end())
return target->second.get();

auto archetype = new Archetype(this, TypeList<Cmpts...>{});
auto archetype = new Archetype(sharedChunkPool.get(), TypeList<Cmpts...>{});
ts2a.emplace(std::move(typeset), std::unique_ptr<Archetype>{ archetype });
for (auto& [query, archetypes] : queryCache) {
if (archetype->GetCmptTypeSet().IsMatch(query))
Expand Down
40 changes: 19 additions & 21 deletions src/core/Archetype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ Archetype::~Archetype() {
}
}
}
for (Chunk* chunk : chunks)
entityMngr->sharedChunkPool.Recycle(chunk);
// FastClear by EntityMngr
//for (Chunk* chunk : chunks)
// entityMngr->sharedChunkPool.Recycle(chunk);
}

Archetype::Archetype(EntityMngr* em, const Archetype& src)
: entityMngr{ em }
Archetype::Archetype(Pool<Chunk>* pool, const Archetype& src)
: chunkPool{ pool }
{
types = src.types;
cmptTraits = src.cmptTraits;
Expand All @@ -41,7 +42,7 @@ Archetype::Archetype(EntityMngr* em, const Archetype& src)
chunks.resize(src.chunks.size(), nullptr);
for (size_t i = 0; i < src.chunks.size(); i++) {
auto srcChunk = src.chunks[i];
auto dstChunk = chunks[i] = entityMngr->sharedChunkPool.Request();
auto dstChunk = chunks[i] = chunkPool->Request();
size_t num = src.EntityNumOfChunk(i);
for (auto type : types.data) {
auto offset = Offsetof(type);
Expand Down Expand Up @@ -85,30 +86,30 @@ void Archetype::SetLayout() {
type2offset.emplace(type, layout.offsets[i++]);
}

Archetype* Archetype::New(EntityMngr* entityMngr, const CmptType* types, size_t num) {
Archetype* Archetype::New(RTDCmptTraits& rtdCmptTraits, Pool<Chunk>* chunkPool, const CmptType* types, size_t num) {
assert(NotContainEntity(types, num));

auto rst = new Archetype{ entityMngr };
auto rst = new Archetype{ chunkPool };
rst->types.Insert(types, num);
rst->types.data.insert(CmptType::Of<Entity>);
rst->cmptTraits.Register<Entity>();
for (size_t i = 0; i < num; i++)
rst->cmptTraits.Register(entityMngr->world->cmptTraits, types[i]);
rst->cmptTraits.Register(rtdCmptTraits, types[i]);
rst->SetLayout();
return rst;
}

Archetype* Archetype::Add(const Archetype* from, const CmptType* types, size_t num) {
Archetype* Archetype::Add(RTDCmptTraits& rtdCmptTraits, const Archetype* from, const CmptType* types, size_t num) {
assert(NotContainEntity(types, num));
assert(!from->types.ContainsAll(types, num));

Archetype* rst = new Archetype{ from->entityMngr };
Archetype* rst = new Archetype{ from->chunkPool };

rst->types = from->types;
rst->cmptTraits = from->cmptTraits;
rst->types.Insert(types, num);
for (size_t i = 0; i < num; i++)
rst->cmptTraits.Register(rst->entityMngr->world->cmptTraits, types[i]);
rst->cmptTraits.Register(rtdCmptTraits, types[i]);

rst->SetLayout();

Expand All @@ -119,7 +120,7 @@ Archetype* Archetype::Remove(const Archetype* from, const CmptType* types, size_
assert(NotContainEntity(types, num));
assert(from->types.ContainsAny(types, num));

Archetype* rst = new Archetype{ from->entityMngr };
Archetype* rst = new Archetype{ from->chunkPool };

rst->types = from->types;
rst->cmptTraits = from->cmptTraits;
Expand All @@ -132,21 +133,20 @@ Archetype* Archetype::Remove(const Archetype* from, const CmptType* types, size_
return rst;
}

size_t Archetype::Create(Entity e) {
size_t Archetype::Create(RTDCmptTraits& rtdCmptTraits, Entity e) {
size_t idx = RequestBuffer();
size_t idxInChunk = idx % chunkCapacity;
byte* buffer = chunks[idx / chunkCapacity]->Data();

const auto& rtdct = entityMngr->world->cmptTraits;
for (const auto& type : types.data) {
if (type.Is<Entity>()) {
constexpr size_t size = sizeof(Entity);
size_t offset = Offsetof(type);
memcpy(buffer + offset + idxInChunk * size, &e, size);
}
else {
auto target = rtdct.GetDefaultConstructors().find(type);
if (target == rtdct.GetDefaultConstructors().end())
auto target = rtdCmptTraits.GetDefaultConstructors().find(type);
if (target == rtdCmptTraits.GetDefaultConstructors().end())
continue;
const auto& ctor = target->second;
size_t size = cmptTraits.Sizeof(type);
Expand All @@ -161,7 +161,7 @@ size_t Archetype::Create(Entity e) {

size_t Archetype::RequestBuffer() {
if (entityNum == chunks.size() * chunkCapacity) {
auto chunk = entityMngr->sharedChunkPool.Request();
auto chunk = chunkPool->Request();
chunks.push_back(chunk);
}
return entityNum++;
Expand Down Expand Up @@ -251,7 +251,7 @@ size_t Archetype::Erase(size_t idx) {
size_t dstIdxInChunk = idx % chunkCapacity;
byte* dstBuffer = chunks[idx / chunkCapacity]->Data();

size_t movedIdx;
size_t movedIdx = size_t_invalid;

if (idx != entityNum - 1) {
size_t movedIdxInArchetype = entityNum - 1;
Expand All @@ -273,8 +273,6 @@ size_t Archetype::Erase(size_t idx) {
}
}
else {
movedIdx = size_t_invalid;

for (const auto& type : types.data) {
size_t size = cmptTraits.Sizeof(type);
size_t offset = Offsetof(type);
Expand All @@ -287,7 +285,7 @@ size_t Archetype::Erase(size_t idx) {

if (chunks.size() * chunkCapacity - entityNum >= chunkCapacity) {
Chunk* chunk = chunks.back();
entityMngr->sharedChunkPool.Recycle(chunk);
chunkPool->Recycle(chunk);
chunks.pop_back();
}

Expand Down
18 changes: 12 additions & 6 deletions src/core/EntityMngr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ size_t EntityMngr::RequestEntityFreeEntry() {
}

EntityMngr::EntityMngr(const EntityMngr& em)
: world{ em.world }
: world{ em.world },
sharedChunkPool{ std::make_unique<Pool<Chunk>>() }
{
ts2a.reserve(em.ts2a.size());
for (const auto& [ts, a] : em.ts2a) {
auto [iter, success] = ts2a.try_emplace(ts, std::make_unique<Archetype>(this, *a));
auto [iter, success] = ts2a.try_emplace(ts, std::make_unique<Archetype>(sharedChunkPool.get(), *a));
assert(success);
}
entityTableFreeEntry = em.entityTableFreeEntry;
Expand All @@ -44,11 +45,16 @@ EntityMngr::EntityMngr(const EntityMngr& em)
}
}

EntityMngr::~EntityMngr() {
ts2a.clear();
sharedChunkPool->FastClear();
}

void EntityMngr::Swap(EntityMngr& rhs) noexcept {
assert(world == rhs.world);

using std::swap;

swap(ts2a, rhs.ts2a);
swap(entityTableFreeEntry, rhs.entityTableFreeEntry);
swap(entityTable, rhs.entityTable);
Expand All @@ -73,7 +79,7 @@ Archetype* EntityMngr::GetOrCreateArchetypeOf(const CmptType* types, size_t num)
if (target != ts2a.end())
return target->second.get();

auto archetype = Archetype::New(this, types, num);
auto archetype = Archetype::New(world->cmptTraits, sharedChunkPool.get(), types, num);

ts2a.emplace(std::move(typeset), std::unique_ptr<Archetype>{ archetype });
for (auto& [query, archetypes] : queryCache) {
Expand All @@ -90,7 +96,7 @@ Entity EntityMngr::Create(const CmptType* types, size_t num) {
EntityInfo& info = entityTable[entityIndex];
Entity e{ entityIndex, info.version };
info.archetype = archetype;
info.idxInArchetype = archetype->Create(e);
info.idxInArchetype = archetype->Create(world->cmptTraits, e);
return e;
}

Expand All @@ -111,7 +117,7 @@ Archetype* EntityMngr::AttachWithoutInit(Entity e, const CmptType* types, size_t
Archetype* dstArchetype;
auto target = ts2a.find(dstCmptTypeSet);
if (target == ts2a.end()) {
dstArchetype = Archetype::Add(srcArchetype, types, num);
dstArchetype = Archetype::Add(world->cmptTraits, srcArchetype, types, num);
assert(dstCmptTypeSet == dstArchetype->GetCmptTypeSet());
for (auto& [query, archetypes] : queryCache) {
if (dstCmptTypeSet.IsMatch(query))
Expand Down

0 comments on commit ea14b33

Please sign in to comment.