From: Mikko Rasa Date: Sun, 7 May 2023 15:07:41 +0000 (+0300) Subject: Keep track of object pools for derived types X-Git-Url: https://git.tdb.fi/?a=commitdiff_plain;h=01f5eed71233dedf5d3463aebde3b8a23b7fbfdc;p=libs%2Fgame.git Keep track of object pools for derived types --- diff --git a/source/game/pool.cpp b/source/game/pool.cpp index 869c571..174a939 100644 --- a/source/game/pool.cpp +++ b/source/game/pool.cpp @@ -1,5 +1,6 @@ #include "pool.h" #include +#include #include using namespace std; @@ -12,10 +13,43 @@ unsigned PoolPool::get_next_id() return next_id++; } +void PoolPool::check_types() +{ + unsigned g = reflector.get_generation(); + if(g==reflector_gen) + return; + + for(const auto &p: pools) + { + const Reflection::ClassBase *type = &p->get_reflected_type(); + PoolBase *parent = nullptr; + while(!parent && type) + { + const vector &bases = type->get_direct_bases(); + if(bases.size()>1) + throw unsupported("Multiple bases in pools are not supported"); + + type = (bases.empty() ? nullptr : bases.front()); + if(type) + { + auto i = ranges::find_if(pools, [type](const auto &o){ return &o->get_reflected_type()==type; }); + if(i!=pools.end()) + parent = i->get(); + } + } + + if(parent) + p->set_parent_pool(*parent); + } + + reflector_gen = g; +} -PoolBase::PoolBase(uint32_t s, DeleteFunc d): + +PoolBase::PoolBase(const Reflection::ClassBase &t, uint32_t s, DeleteFunc d): object_size(s), - deleter(d) + deleter(d), + reflected_type(t) { } PoolBase::~PoolBase() @@ -23,6 +57,22 @@ PoolBase::~PoolBase() destroy_all(); } +void PoolBase::set_parent_pool(PoolBase &p) +{ + if(!p.reflected_type.is_direct_base_of(reflected_type)) + throw invalid_argument("PoolBase::set_parent_pool"); + + if(parent_pool) + { + auto i = ranges::find(parent_pool->derived_pools, this); + if(i!=parent_pool->derived_pools.end()) + parent_pool->derived_pools.erase(i); + } + + parent_pool = &p; + parent_pool->derived_pools.push_back(this); +} + void PoolBase::destroy_all() { if(object_count>0) diff --git a/source/game/pool.h b/source/game/pool.h index fd383fc..dde179d 100644 --- a/source/game/pool.h +++ b/source/game/pool.h @@ -6,6 +6,7 @@ #include #include #include "mspgame_api.h" +#include "reflection.h" namespace Msp::Game { @@ -17,16 +18,20 @@ class Pool; class MSPGAME_API PoolPool: public NonCopyable { private: + Reflection::Reflector &reflector; std::vector> pools; + unsigned reflector_gen = 0; public: - PoolPool() = default; + PoolPool(Reflection::Reflector &r): reflector(r) { } PoolPool(PoolPool &&) = default; PoolPool &operator=(PoolPool &&) = default; private: static unsigned get_next_id(); + void check_types(); + public: template static unsigned get_type_id() { static unsigned id = get_next_id(); return id; } @@ -53,11 +58,18 @@ private: std::uint32_t capacity = 0; DeleteFunc *deleter = nullptr; + const Reflection::ClassBase &reflected_type; + PoolBase *parent_pool = nullptr; + std::vector derived_pools; + protected: - PoolBase(std::uint32_t, DeleteFunc); + PoolBase(const Reflection::ClassBase &, std::uint32_t, DeleteFunc); public: virtual ~PoolBase(); + const Reflection::ClassBase &get_reflected_type() const { return reflected_type; } + void set_parent_pool(PoolBase &); + protected: void destroy_all(); @@ -80,7 +92,7 @@ template class Pool: public PoolBase { public: - Pool(): PoolBase(sizeof(T), delete_object) { } + Pool(Reflection::Reflector &r): PoolBase(r.get_or_create_class(), sizeof(T), delete_object) { } template T *create(Args &&...); @@ -103,7 +115,9 @@ inline Pool &PoolPool::get_pool() std::unique_ptr &ptr = pools[id]; if(!ptr) - ptr = std::make_unique>(); + ptr = std::make_unique>(reflector); + + check_types(); return *static_cast *>(ptr.get()); } diff --git a/source/game/reflection.h b/source/game/reflection.h index d42c860..bfd4aeb 100644 --- a/source/game/reflection.h +++ b/source/game/reflection.h @@ -57,6 +57,7 @@ public: const std::type_index &get_type() const { return type; } const std::string &get_name() const { return name; } + const std::vector &get_direct_bases() const { return bases; } bool is_direct_base_of(const ClassBase &) const; bool is_base_of(const ClassBase &) const; diff --git a/source/game/stage.cpp b/source/game/stage.cpp index 3888410..3a2f5cd 100644 --- a/source/game/stage.cpp +++ b/source/game/stage.cpp @@ -13,6 +13,7 @@ namespace Msp::Game { Stage::Stage(Reflection::Reflector &f, DataFile::Collection &r): reflector(f), resources(r), + pools(reflector), event_source(event_bus), event_observer(event_bus), root(std::make_unique(*this)),