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 */

Generated on Sun Mar 15 22:49:48 2009 for openttd by  doxygen 1.5.6