# oldpool.h

Go to the documentation of this file.

    00001 /* $Id: oldpool.h 15718 2009-03-15 00:32:18Z rubidium $ */
    00002
    00005 #ifndef OLDPOOL_H
    00006 #define OLDPOOL_H
    00007
    00008 #include "core/math_func.hpp"
    00009
    00010 /* The function that is called after a new block is added
    00011      start_item is the first item of the new made block */
    00012 typedef void OldMemoryPoolNewBlock(uint start_item);
    00013 /* The function that is called before a block is cleaned up */
    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 /* OLDPOOL_H */