pool_type.hpp

Go to the documentation of this file.
00001 /* $Id$ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef POOL_TYPE_HPP
00013 #define POOL_TYPE_HPP
00014 
00015 #include "smallvec_type.hpp"
00016 #include "enum_type.hpp"
00017 
00019 enum PoolType {
00020   PT_NONE    = 0x00, 
00021   PT_NORMAL  = 0x01, 
00022   PT_NCLIENT = 0x02, 
00023   PT_NADMIN  = 0x04, 
00024   PT_DATA    = 0x08, 
00025   PT_ALL     = 0x0F, 
00026 };
00027 DECLARE_ENUM_AS_BIT_SET(PoolType)
00028 
00029 typedef SmallVector<struct PoolBase *, 4> PoolVector; 
00030 
00032 struct PoolBase {
00033   const PoolType type; 
00034 
00039   static PoolVector *GetPools()
00040   {
00041     static PoolVector *pools = new PoolVector();
00042     return pools;
00043   }
00044 
00045   static void Clean(PoolType);
00046 
00051   PoolBase(PoolType pt) : type(pt)
00052   {
00053     *PoolBase::GetPools()->Append() = this;
00054   }
00055 
00056   virtual ~PoolBase();
00057 
00061   virtual void CleanPool() = 0;
00062 };
00063 
00075 template <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size, PoolType Tpool_type = PT_NORMAL, bool Tcache = false, bool Tzero = true>
00076 struct Pool : PoolBase {
00077   static const size_t MAX_SIZE = Tmax_size; 
00078 
00079   const char * const name; 
00080 
00081   size_t size;         
00082   size_t first_free;   
00083   size_t first_unused; 
00084   size_t items;        
00085 #ifdef OTTD_ASSERT
00086   size_t checked;      
00087 #endif /* OTTD_ASSERT */
00088   bool cleaning;       
00089 
00090   Titem **data;        
00091 
00092   Pool(const char *name);
00093   virtual void CleanPool();
00094 
00101   FORCEINLINE Titem *Get(size_t index)
00102   {
00103     assert(index < this->first_unused);
00104     return this->data[index];
00105   }
00106 
00112   FORCEINLINE bool IsValidID(size_t index)
00113   {
00114     return index < this->first_unused && this->Get(index) != NULL;
00115   }
00116 
00122   FORCEINLINE bool CanAllocate(size_t n = 1)
00123   {
00124     bool ret = this->items <= Tmax_size - n;
00125 #ifdef OTTD_ASSERT
00126     this->checked = ret ? n : 0;
00127 #endif /* OTTD_ASSERT */
00128     return ret;
00129   }
00130 
00135   template <struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero> *Tpool>
00136   struct PoolItem {
00137     Tindex index; 
00138 
00145     FORCEINLINE void *operator new(size_t size)
00146     {
00147       return Tpool->GetNew(size);
00148     }
00149 
00155     FORCEINLINE void operator delete(void *p)
00156     {
00157       Titem *pn = (Titem *)p;
00158       assert(pn == Tpool->Get(pn->index));
00159       Tpool->FreeItem(pn->index);
00160     }
00161 
00170     FORCEINLINE void *operator new(size_t size, size_t index)
00171     {
00172       return Tpool->GetNew(size, index);
00173     }
00174 
00183     FORCEINLINE void *operator new(size_t size, void *ptr)
00184     {
00185       for (size_t i = 0; i < Tpool->first_unused; i++) {
00186         /* Don't allow creating new objects over existing.
00187          * Even if we called the destructor and reused this memory,
00188          * we don't know whether 'size' and size of currently allocated
00189          * memory are the same (because of possible inheritance).
00190          * Use { size_t index = item->index; delete item; new (index) item; }
00191          * instead to make sure destructor is called and no memory leaks. */
00192         assert(ptr != Tpool->data[i]);
00193       }
00194       return ptr;
00195     }
00196 
00197 
00205     static FORCEINLINE bool CanAllocateItem(size_t n = 1)
00206     {
00207       return Tpool->CanAllocate(n);
00208     }
00209 
00214     static FORCEINLINE bool CleaningPool()
00215     {
00216       return Tpool->cleaning;
00217     }
00218 
00224     static FORCEINLINE bool IsValidID(size_t index)
00225     {
00226       return Tpool->IsValidID(index);
00227     }
00228 
00235     static FORCEINLINE Titem *Get(size_t index)
00236     {
00237       return Tpool->Get(index);
00238     }
00239 
00246     static FORCEINLINE Titem *GetIfValid(size_t index)
00247     {
00248       return index < Tpool->first_unused ? Tpool->Get(index) : NULL;
00249     }
00250 
00256     static FORCEINLINE size_t GetPoolSize()
00257     {
00258       return Tpool->first_unused;
00259     }
00260 
00265     static FORCEINLINE size_t GetNumItems()
00266     {
00267       return Tpool->items;
00268     }
00269 
00277     static FORCEINLINE void PostDestructor(size_t index) { }
00278   };
00279 
00280 private:
00281   static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t); 
00282 
00287   struct AllocCache {
00289     AllocCache *next;
00290   };
00291 
00293   AllocCache *alloc_cache;
00294 
00295   void *AllocateItem(size_t size, size_t index);
00296   void ResizeFor(size_t index);
00297   size_t FindFirstFree();
00298 
00299   void *GetNew(size_t size);
00300   void *GetNew(size_t size, size_t index);
00301 
00302   void FreeItem(size_t index);
00303 };
00304 
00305 #define FOR_ALL_ITEMS_FROM(type, iter, var, start) \
00306   for (size_t iter = start; var = NULL, iter < type::GetPoolSize(); iter++) \
00307     if ((var = type::Get(iter)) != NULL)
00308 
00309 #define FOR_ALL_ITEMS(type, iter, var) FOR_ALL_ITEMS_FROM(type, iter, var, 0)
00310 
00311 #endif /* POOL_TYPE_HPP */

Generated on Fri Jun 3 05:18:50 2011 for OpenTTD by  doxygen 1.6.1