1 #ifndef MSP_GAME_POOL_H_
2 #define MSP_GAME_POOL_H_
7 #include <msp/core/noncopyable.h>
8 #include "mspgame_api.h"
17 class MSPGAME_API PoolPool: public NonCopyable
20 std::vector<std::unique_ptr<PoolBase>> pools;
24 PoolPool(PoolPool &&) = default;
25 PoolPool &operator=(PoolPool &&) = default;
28 static unsigned get_next_id();
32 static unsigned get_type_id() { static unsigned id = get_next_id(); return id; }
39 class MSPGAME_API PoolBase: public NonCopyable
42 using DeleteFunc = void(void *);
43 using FlagType = uint32_t;
45 static constexpr std::size_t BLOCK_SIZE = 512;
46 static constexpr std::size_t BLOCK_ALIGNMENT = 64;
47 static constexpr std::size_t FLAG_BITS = sizeof(FlagType)*8;
49 std::size_t object_size = 0;
50 char **blocks = nullptr;
51 std::uint32_t *free_list = nullptr;
52 std::uint32_t object_count = 0;
53 std::uint32_t capacity = 0;
54 DeleteFunc *deleter = nullptr;
57 PoolBase(std::uint32_t, DeleteFunc);
59 PoolBase(PoolBase &&);
60 PoolBase &operator=(PoolBase &&);
67 void iterate_objects(const F &);
69 void *prepare_allocate();
70 void commit_allocate(void *);
76 std::uint32_t get_capacity() const { return capacity; }
82 class Pool: public PoolBase
85 Pool(): PoolBase(sizeof(T), delete_object) { }
87 template<typename... Args>
88 T *create(Args &&...);
91 void iterate_objects(const F &func)
92 { PoolBase::iterate_objects([&func](void *ptr){ func(*static_cast<T *>(ptr)); }); }
95 static void delete_object(void *ptr) { std::destroy_at(static_cast<T *>(ptr)); }
100 inline Pool<T> &PoolPool::get_pool()
102 unsigned id = get_type_id<T>();
106 std::unique_ptr<PoolBase> &ptr = pools[id];
108 ptr = std::make_unique<Pool<T>>();
110 return *static_cast<Pool<T> *>(ptr.get());
115 inline void PoolBase::iterate_objects(const F &func)
117 unsigned block_count = capacity/BLOCK_SIZE;
118 for(unsigned i=0; i<block_count; ++i)
120 char *ptr = blocks[i];
121 const FlagType *flags = reinterpret_cast<FlagType *>(ptr+BLOCK_SIZE*object_size);
122 for(unsigned j=0; j<BLOCK_SIZE; j+=FLAG_BITS)
124 char *end = ptr+FLAG_BITS*object_size;
125 if(FlagType f = *flags)
127 if(!static_cast<FlagType>(~f))
129 for(; ptr!=end; ptr+=object_size)
130 func(static_cast<void *>(ptr));
134 for(; ptr!=end; ptr+=object_size, f>>=1)
136 func(static_cast<void *>(ptr));
148 template<typename... Args>
149 inline T *Pool<T>::create(Args &&... args)
151 void *ptr = prepare_allocate();
152 T *obj = std::construct_at(static_cast<T *>(ptr), std::forward<Args>(args)...);
153 commit_allocate(ptr);
157 } // namespace Msp::Game