oldpool.h

Go to the documentation of this file.
00001 /* $Id: oldpool.h 12864 2008-04-24 11:48:09Z 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 
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     /* Check if we can add a block to the pool */
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     /* Check if we can add a block to the pool */
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 /* OLDPOOL_H */

Generated on Mon Sep 22 20:34:17 2008 for openttd by  doxygen 1.5.6