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
00158
00163 template <typename T, typename Tid, OldMemoryPool<T> *Tpool>
00164 struct PoolItem {
00168 Tid index;
00169
00177 virtual ~PoolItem()
00178 {
00179
00180 }
00181
00189 PoolItem()
00190 {
00191
00192 }
00193
00199 void *operator new(size_t size)
00200 {
00201 return AllocateRaw();
00202 }
00203
00209 void operator delete(void *p)
00210 {
00211 Tpool->UpdateFirstFreeIndex(((T*)p)->index);
00212 }
00213
00221 void *operator new(size_t size, int index)
00222 {
00223 if (!Tpool->AddBlockIfNeeded(index)) error("%s: failed loading savegame: too many %s", Tpool->GetName(), Tpool->GetName());
00224
00225 return Tpool->Get(index);
00226 }
00227
00234 void operator delete(void *p, int index)
00235 {
00236 Tpool->UpdateFirstFreeIndex(index);
00237 }
00238
00246 void *operator new(size_t size, T *pn)
00247 {
00248 return pn;
00249 }
00250
00257 void operator delete(void *p, T *pn)
00258 {
00259 Tpool->UpdateFirstFreeIndex(pn->index);
00260 }
00261
00262 private:
00269 static inline T *AllocateSafeRaw(uint &first)
00270 {
00271 uint last_minus_one = Tpool->GetSize() - 1;
00272
00273 for (T *t = Tpool->Get(first); t != NULL; t = (t->index < last_minus_one) ? Tpool->Get(t->index + 1U) : NULL) {
00274 if (!t->IsValid()) {
00275 first = t->index;
00276 Tid index = t->index;
00277
00278 memset(t, 0, Tpool->item_size);
00279 t->index = index;
00280 return t;
00281 }
00282 }
00283
00284
00285 if (Tpool->AddBlockToPool()) return AllocateRaw(first);
00286
00287 return NULL;
00288 }
00289
00290 protected:
00295 static inline T *AllocateRaw()
00296 {
00297 return AllocateSafeRaw(Tpool->first_free_index);
00298 }
00299
00305 static inline T *AllocateRaw(uint &first)
00306 {
00307 if (first >= Tpool->GetSize() && !Tpool->AddBlockToPool()) return NULL;
00308
00309 return AllocateSafeRaw(first);
00310 }
00311
00316 static inline bool CleaningPool()
00317 {
00318 return Tpool->CleaningPool();
00319 }
00320
00321 public:
00328 static inline bool CanAllocateItem()
00329 {
00330 uint last_minus_one = Tpool->GetSize() - 1;
00331
00332 for (T *t = Tpool->Get(Tpool->first_free_index); t != NULL; t = (t->index < last_minus_one) ? Tpool->Get(t->index + 1U) : NULL) {
00333 if (!t->IsValid()) return true;
00334 Tpool->first_free_index = t->index;
00335 }
00336
00337
00338 if (Tpool->AddBlockToPool()) return CanAllocateItem();
00339
00340 return false;
00341 }
00342 };
00343
00344
00345 #define OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \
00346 enum { \
00347 name##_POOL_BLOCK_SIZE_BITS = block_size_bits, \
00348 name##_POOL_MAX_BLOCKS = max_blocks \
00349 };
00350
00351
00352 #define OLD_POOL_ACCESSORS(name, type) \
00353 static inline type* Get##name(uint index) { return _##name##_pool.Get(index); } \
00354 static inline uint Get##name##PoolSize() { return _##name##_pool.GetSize(); }
00355
00356
00357 #define DECLARE_OLD_POOL(name, type, block_size_bits, max_blocks) \
00358 OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \
00359 extern OldMemoryPool<type> _##name##_pool; \
00360 OLD_POOL_ACCESSORS(name, type)
00361
00362
00363 #define DEFINE_OLD_POOL(name, type, new_block_proc, clean_block_proc) \
00364 OldMemoryPool<type> _##name##_pool( \
00365 #name, name##_POOL_MAX_BLOCKS, name##_POOL_BLOCK_SIZE_BITS, sizeof(type), \
00366 new_block_proc, clean_block_proc);
00367
00368 #define DEFINE_OLD_POOL_GENERIC(name, type) \
00369 OldMemoryPool<type> _##name##_pool( \
00370 #name, name##_POOL_MAX_BLOCKS, name##_POOL_BLOCK_SIZE_BITS, sizeof(type), \
00371 PoolNewBlock<type, &_##name##_pool>, PoolCleanBlock<type, &_##name##_pool>);
00372
00373
00374 #define STATIC_OLD_POOL(name, type, block_size_bits, max_blocks, new_block_proc, clean_block_proc) \
00375 OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \
00376 static DEFINE_OLD_POOL(name, type, new_block_proc, clean_block_proc) \
00377 OLD_POOL_ACCESSORS(name, type)
00378
00379 #endif