1 #ifndef MSP_GAME_POOL_H_
2 #define MSP_GAME_POOL_H_
7 #include <msp/core/noncopyable.h>
16 class PoolPool: public NonCopyable
19 std::vector<std::unique_ptr<PoolBase>> pools;
23 PoolPool(PoolPool &&) = default;
24 PoolPool &operator=(PoolPool &&) = default;
27 static unsigned get_next_id();
31 static unsigned get_type_id() { static unsigned id = get_next_id(); return id; }
38 class PoolBase: public NonCopyable
41 using DeleteFunc = void(void *);
42 using FlagType = uint32_t;
44 static constexpr std::size_t BLOCK_SIZE = 512;
45 static constexpr std::size_t BLOCK_ALIGNMENT = 64;
46 static constexpr std::size_t FLAG_BITS = sizeof(FlagType)*8;
48 std::size_t object_size = 0;
49 char **blocks = nullptr;
50 std::uint32_t *free_list = nullptr;
51 std::uint32_t object_count = 0;
52 std::uint32_t capacity = 0;
53 DeleteFunc *deleter = nullptr;
56 PoolBase(std::uint32_t, DeleteFunc);
58 PoolBase(PoolBase &&);
59 PoolBase &operator=(PoolBase &&);
66 void iterate_objects(const F &);
68 void *prepare_allocate();
69 void commit_allocate(void *);
75 std::uint32_t get_capacity() const { return capacity; }
81 class Pool: public PoolBase
84 Pool(): PoolBase(sizeof(T), delete_object) { }
86 template<typename... Args>
87 T *create(Args &&...);
90 void iterate_objects(const F &func)
91 { PoolBase::iterate_objects([&func](void *ptr){ func(*static_cast<T *>(ptr)); }); }
94 static void delete_object(void *ptr) { std::destroy_at(static_cast<T *>(ptr)); }
99 inline Pool<T> &PoolPool::get_pool()
101 unsigned id = get_type_id<T>();
105 std::unique_ptr<PoolBase> &ptr = pools[id];
107 ptr = std::make_unique<Pool<T>>();
109 return *static_cast<Pool<T> *>(ptr.get());
114 inline void PoolBase::iterate_objects(const F &func)
116 unsigned block_count = capacity/BLOCK_SIZE;
117 for(unsigned i=0; i<block_count; ++i)
119 char *ptr = blocks[i];
120 const FlagType *flags = reinterpret_cast<FlagType *>(ptr+BLOCK_SIZE*object_size);
121 for(unsigned j=0; j<BLOCK_SIZE; j+=FLAG_BITS)
123 char *end = ptr+FLAG_BITS*object_size;
124 if(FlagType f = *flags)
126 if(!static_cast<FlagType>(~f))
128 for(; ptr!=end; ptr+=object_size)
129 func(static_cast<void *>(ptr));
133 for(; ptr!=end; ptr+=object_size, f>>=1)
135 func(static_cast<void *>(ptr));
147 template<typename... Args>
148 inline T *Pool<T>::create(Args &&... args)
150 void *ptr = prepare_allocate();
151 T *obj = std::construct_at(static_cast<T *>(ptr), std::forward<Args>(args)...);
152 commit_allocate(ptr);
156 } // namespace Msp::Game