#include "pool.h"
#include <stdexcept>
+#include <msp/core/except.h>
#include <msp/io/print.h>
using namespace std;
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<const Reflection::ClassBase *> &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()
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)
#include <vector>
#include <msp/core/noncopyable.h>
#include "mspgame_api.h"
+#include "reflection.h"
namespace Msp::Game {
class MSPGAME_API PoolPool: public NonCopyable
{
private:
+ Reflection::Reflector &reflector;
std::vector<std::unique_ptr<PoolBase>> 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<typename T>
static unsigned get_type_id() { static unsigned id = get_next_id(); return id; }
std::uint32_t capacity = 0;
DeleteFunc *deleter = nullptr;
+ const Reflection::ClassBase &reflected_type;
+ PoolBase *parent_pool = nullptr;
+ std::vector<PoolBase *> 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();
class Pool: public PoolBase
{
public:
- Pool(): PoolBase(sizeof(T), delete_object) { }
+ Pool(Reflection::Reflector &r): PoolBase(r.get_or_create_class<T>(), sizeof(T), delete_object) { }
template<typename... Args>
T *create(Args &&...);
std::unique_ptr<PoolBase> &ptr = pools[id];
if(!ptr)
- ptr = std::make_unique<Pool<T>>();
+ ptr = std::make_unique<Pool<T>>(reflector);
+
+ check_types();
return *static_cast<Pool<T> *>(ptr.get());
}
const std::type_index &get_type() const { return type; }
const std::string &get_name() const { return name; }
+ const std::vector<const ClassBase *> &get_direct_bases() const { return bases; }
bool is_direct_base_of(const ClassBase &) const;
bool is_base_of(const ClassBase &) const;
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<Root>(*this)),