]> git.tdb.fi Git - libs/game.git/commitdiff
Trigger reflected base class discovery from the pool allocator
authorMikko Rasa <tdb@tdb.fi>
Tue, 22 Apr 2025 21:15:40 +0000 (00:15 +0300)
committerMikko Rasa <tdb@tdb.fi>
Tue, 22 Apr 2025 21:28:00 +0000 (00:28 +0300)
This makes it run when a previously unseen intermediate base class is
requested, even if it does not own any components.

source/game/owned.h
source/game/pool.cpp
source/game/pool.h

index bb09433da3bd21b819dfeb9e61080e8cce29c80d..baebf9c8c17a975d6b87664eb5890023b9698654 100644 (file)
@@ -70,19 +70,14 @@ Owned<T>::Owned(Handle<P> parent, Args &&... args)
 
        Stage &stage = get_stage(*parent);
        Pool<T> &pool = stage.get_pools().get_pool<T>();
-       bool first_created = !pool.get_capacity();
        this->ptr = pool.create(parent, std::forward<Args>(args)...);
        if constexpr(std::is_base_of_v<Component, T>)
        {
-               if(first_created)
-                       stage.get_reflector().get_or_create_class<T>().discover_bases(this->ptr);
                parent->add_component(*this);
                stage.get_event_source().emit<Events::ComponentCreated>(*this);
        }
        else
        {
-               if(first_created)
-                       stage.get_reflector().get_or_create_class<T>().discover_bases(this->ptr);
                parent->add_child(*this);
                stage.get_event_source().emit<Events::EntityCreated>(*this);
        }
index ada1276bb2ab0e7b9cd57d8a5e155c110c054e20..427ea4f92b82349907c519f8330151a4e9681676 100644 (file)
@@ -1,4 +1,5 @@
 #include "pool.h"
+#include <bit>
 #include <stdexcept>
 #include <msp/core/except.h>
 #include <msp/io/print.h>
@@ -15,6 +16,9 @@ unsigned PoolPool::get_next_id()
 
 void PoolPool::check_types()
 {
+       for(const auto &p: pools)
+               p->update_reflection();
+
        for(const auto &p: pools)
        {
                const Reflection::ClassBase *type = &p->get_reflected_type();
@@ -42,7 +46,7 @@ void PoolPool::check_types()
 }
 
 
-PoolBase::PoolBase(const Reflection::ClassBase &t, uint32_t s, DeleteFunc d):
+PoolBase::PoolBase(Reflection::ClassBase &t, uint32_t s, DeleteFunc d):
        object_size(s),
        deleter(d),
        reflected_type(t)
@@ -53,6 +57,21 @@ PoolBase::~PoolBase()
        destroy_all();
 }
 
+void PoolBase::update_reflection() const
+{
+       if(!object_count || reflected_type.is_up_to_date())
+               return;
+
+       unsigned block_count = capacity/BLOCK_SIZE;
+       for(unsigned i=0; i<block_count; ++i)
+       {
+               auto flags_ptr = reinterpret_cast<const FlagType *>(blocks[i]+BLOCK_SIZE*object_size);
+               for(unsigned j=0; j<BLOCK_SIZE; j+=FLAG_BITS)
+                       if(FlagType f = flags_ptr[j/FLAG_BITS])
+                               return reflected_type.discover_bases(blocks[i]+(j+countr_zero(f))*object_size);
+       }
+}
+
 void PoolBase::set_parent_pool(PoolBase &p)
 {
        if(!p.reflected_type.is_direct_base_of(reflected_type))
index b734852764e89c4519b9a19e789de8ffeebdba48..4555c0d9b166d37e672f3aae6e5d2788c86f046c 100644 (file)
@@ -58,16 +58,17 @@ private:
        std::uint32_t capacity = 0;
        DeleteFunc *deleter = nullptr;
 
-       const Reflection::ClassBase &reflected_type;
+       Reflection::ClassBase &reflected_type;
        PoolBase *parent_pool = nullptr;
        std::vector<PoolBase *> derived_pools;
 
 protected:
-       PoolBase(const Reflection::ClassBase &, std::uint32_t, DeleteFunc);
+       PoolBase(Reflection::ClassBase &, std::uint32_t, DeleteFunc);
 public:
        virtual ~PoolBase();
 
        const Reflection::ClassBase &get_reflected_type() const { return reflected_type; }
+       void update_reflection() const;
        void set_parent_pool(PoolBase &);
 
 protected:
@@ -169,9 +170,12 @@ template<typename T>
 template<typename... Args>
 inline T *Pool<T>::create(Args &&... args)
 {
+       bool first_created = !get_capacity();
        void *ptr = prepare_allocate();
        T *obj = std::construct_at(static_cast<T *>(ptr), std::forward<Args>(args)...);
        commit_allocate(ptr);
+       if(first_created)
+               update_reflection();
        return obj;
 }