00001
00002
00005 #ifndef OLDPOOL_H
00006 #define OLDPOOL_H
00007
00008 #include "core/math_func.hpp"
00009
00010
00011
00012 typedef void OldMemoryPoolNewBlock(uint start_item);
00013
00014 typedef void OldMemoryPoolCleanBlock(uint start_item, uint end_item);
00015
00020 struct OldMemoryPoolBase {
00021 void CleanPool();
00022 bool AddBlockToPool();
00023 bool AddBlockIfNeeded(uint index);
00024
00025 protected:
00026 OldMemoryPoolBase(const char *name, uint max_blocks, uint block_size_bits, uint item_size,
00027 OldMemoryPoolNewBlock *new_block_proc, OldMemoryPoolCleanBlock *clean_block_proc) :
00028 name(name), max_blocks(max_blocks), block_size_bits(block_size_bits),
00029 new_block_proc(new_block_proc), clean_block_proc(clean_block_proc), current_blocks(0),
00030 total_items(0), cleaning_pool(false), item_size(item_size), first_free_index(0), blocks(NULL) {}
00031
00032 const char *name;
00033
00034 const uint max_blocks;
00035 const uint block_size_bits;
00036
00038 OldMemoryPoolNewBlock *new_block_proc;
00040 OldMemoryPoolCleanBlock *clean_block_proc;
00041
00042 uint current_blocks;
00043 uint total_items;
00044
00045 bool cleaning_pool;
00046 public:
00047 const uint item_size;
00048 uint first_free_index;
00049 byte **blocks;
00050
00056 inline void UpdateFirstFreeIndex(uint index)
00057 {
00058 first_free_index = min(first_free_index, index);
00059 }
00060
00067 inline uint GetSize() const
00068 {
00069 return this->total_items;
00070 }
00071
00078 inline bool CanAllocateMoreBlocks() const
00079 {
00080 return this->current_blocks < this->max_blocks;
00081 }
00082
00087 inline uint GetBlockCount() const
00088 {
00089 return this->current_blocks;
00090 }
00091
00096 inline const char *GetName() const
00097 {
00098 return this->name;
00099 }
00100
00105 inline bool CleaningPool() const
00106 {
00107 return this->cleaning_pool;
00108 }
00109 };
00110
00111 template <typename T>
00112 struct OldMemoryPool : public OldMemoryPoolBase {
00113 OldMemoryPool(const char *name, uint max_blocks, uint block_size_bits, uint item_size,
00114 OldMemoryPoolNewBlock *new_block_proc, OldMemoryPoolCleanBlock *clean_block_proc) :
00115 OldMemoryPoolBase(name, max_blocks, block_size_bits, item_size, new_block_proc, clean_block_proc) {}
00116
00123 inline T *Get(uint index) const
00124 {
00125 assert(index < this->GetSize());
00126 return (T*)(this->blocks[index >> this->block_size_bits] +
00127 (index & ((1 << this->block_size_bits) - 1)) * this->item_size);
00128 }
00129 };
00130
00135 template <typename T, OldMemoryPool<T> *Tpool>
00136 static void PoolNewBlock(uint start_item)
00137 {
00138 for (T *t = Tpool->Get(start_item); t != NULL; t = (t->index + 1U < Tpool->GetSize()) ? Tpool->Get(t->index + 1U) : NULL) {
00139 t = new (t) T();
00140 t->index = start_item++;
00141 }
00142 }
00143
00149 template <typename T, OldMemoryPool<T> *Tpool>
00150 static void PoolCleanBlock(uint start_item, uint end_item)
00151 {
00152 for (uint i = start_item; i <= end_item; i++) {
00153 T *t = Tpool->Get(i);
00154 delete t;
00155 }
00156 }
00157
00162 template <typename T>
00163 struct PoolItemIndexLess {
00170 bool operator()(const T *lhs, const T *rhs) const
00171 {
00172 return lhs->index < rhs->index;
00173 }
00174 };
00175
00180 template <typename T, typename Tid, OldMemoryPool<T> *Tpool>
00181 struct PoolItem {
00185 Tid index;
00186
00194 virtual ~PoolItem()
00195 {
00196
00197 }
00198
00206 PoolItem()
00207 {
00208
00209 }
00210
00217 void *operator new(size_t size)
00218 {
00219 return AllocateRaw();
00220 }
00221
00227 void operator delete(void *p)
00228 {
00229 Tpool->UpdateFirstFreeIndex(((T*)p)->index);
00230 }
00231
00239 void *operator new(size_t size, int index)
00240 {
00241 if (!Tpool->AddBlockIfNeeded(index)) error("%s: failed loading savegame: too many %s", Tpool->GetName(), Tpool->GetName());
00242
00243 return Tpool->Get(index);
00244 }
00245
00252 void operator delete(void *p, int index)
00253 {
00254 Tpool->UpdateFirstFreeIndex(index);
00255 }
00256
00264 void *operator new(size_t size, T *pn)
00265 {
00266 return pn;
00267 }
00268
00275 void operator delete(void *p, T *pn)
00276 {
00277 Tpool->UpdateFirstFreeIndex(pn->index);
00278 }
00279
00280 private:
00281 static T *AllocateSafeRaw(uint &first);
00282
00283 protected:
00289 static inline T *AllocateRaw()
00290 {
00291 return AllocateSafeRaw(Tpool->first_free_index);
00292 }
00293
00300 static inline T *AllocateRaw(uint &first)
00301 {
00302 if (first >= Tpool->GetSize() && !Tpool->AddBlockToPool()) return NULL;
00303
00304 return AllocateSafeRaw(first);
00305 }
00306
00311 static inline bool CleaningPool()
00312 {
00313 return Tpool->CleaningPool();
00314 }
00315
00316 public:
00317 static bool CanAllocateItem(uint count = 1);
00318 };
00319
00320
00321 #define OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \
00322 enum { \
00323 name##_POOL_BLOCK_SIZE_BITS = block_size_bits, \
00324 name##_POOL_MAX_BLOCKS = max_blocks \
00325 };
00326
00327
00328 #define OLD_POOL_ACCESSORS(name, type) \
00329 static inline type *Get##name(uint index) { return _##name##_pool.Get(index); } \
00330 static inline uint Get##name##PoolSize() { return _##name##_pool.GetSize(); }
00331
00332
00333 #define DECLARE_OLD_POOL(name, type, block_size_bits, max_blocks) \
00334 OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \
00335 extern OldMemoryPool<type> _##name##_pool; \
00336 OLD_POOL_ACCESSORS(name, type)
00337
00338
00339 #define DEFINE_OLD_POOL(name, type, new_block_proc, clean_block_proc) \
00340 OldMemoryPool<type> _##name##_pool( \
00341 #name, name##_POOL_MAX_BLOCKS, name##_POOL_BLOCK_SIZE_BITS, sizeof(type), \
00342 new_block_proc, clean_block_proc);
00343
00344 #define DEFINE_OLD_POOL_GENERIC(name, type) \
00345 OldMemoryPool<type> _##name##_pool( \
00346 #name, name##_POOL_MAX_BLOCKS, name##_POOL_BLOCK_SIZE_BITS, sizeof(type), \
00347 PoolNewBlock<type, &_##name##_pool>, PoolCleanBlock<type, &_##name##_pool>); \
00348 template type *PoolItem<type, type##ID, &_##name##_pool>::AllocateSafeRaw(uint &first); \
00349 template bool PoolItem<type, type##ID, &_##name##_pool>::CanAllocateItem(uint count);
00350
00351
00352 #define STATIC_OLD_POOL(name, type, block_size_bits, max_blocks, new_block_proc, clean_block_proc) \
00353 OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \
00354 static DEFINE_OLD_POOL(name, type, new_block_proc, clean_block_proc) \
00355 OLD_POOL_ACCESSORS(name, type)
00356
00357 #endif