# pool_type.hpp

Go to the documentation of this file.

    00001 /* $Id: pool_type.hpp 26333 2014-02-11 20:34:48Z frosch $ */
    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 private:
    00068   PoolBase(const PoolBase &other);
    00069 };
    00070
    00082 template <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size, PoolType Tpool_type = PT_NORMAL, bool Tcache = false, bool Tzero = true>
    00083 struct Pool : PoolBase {
    00084   /* Ensure Tmax_size is within the bounds of Tindex. */
    00085   assert_compile((uint64)(Tmax_size - 1) >> 8 * sizeof(Tindex) == 0);
    00086
    00087   static const size_t MAX_SIZE = Tmax_size;
    00088
    00089   const char * const name;
    00090
    00091   size_t size;
    00092   size_t first_free;
    00093   size_t first_unused;
    00094   size_t items;
    00095 #ifdef OTTD_ASSERT
    00096   size_t checked;
    00097 #endif /* OTTD_ASSERT */
    00098   bool cleaning;
    00099
    00100   Titem **data;
    00101
    00102   Pool(const char *name);
    00103   virtual void CleanPool();
    00104
    00111   inline Titem *Get(size_t index)
    00112   {
    00113     assert(index < this->first_unused);
    00114     return this->data[index];
    00115   }
    00116
    00122   inline bool IsValidID(size_t index)
    00123   {
    00124     return index < this->first_unused && this->Get(index) != NULL;
    00125   }
    00126
    00132   inline bool CanAllocate(size_t n = 1)
    00133   {
    00134     bool ret = this->items <= Tmax_size - n;
    00135 #ifdef OTTD_ASSERT
    00136     this->checked = ret ? n : 0;
    00137 #endif /* OTTD_ASSERT */
    00138     return ret;
    00139   }
    00140
    00145   template <struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero> *Tpool>
    00146   struct PoolItem {
    00147     Tindex index;
    00148
    00155     inline void *operator new(size_t size)
    00156     {
    00157       return Tpool->GetNew(size);
    00158     }
    00159
    00165     inline void operator delete(void *p)
    00166     {
    00167       if (p == NULL) return;
    00168       Titem *pn = (Titem *)p;
    00169       assert(pn == Tpool->Get(pn->index));
    00170       Tpool->FreeItem(pn->index);
    00171     }
    00172
    00181     inline void *operator new(size_t size, size_t index)
    00182     {
    00183       return Tpool->GetNew(size, index);
    00184     }
    00185
    00194     inline void *operator new(size_t size, void *ptr)
    00195     {
    00196       for (size_t i = 0; i < Tpool->first_unused; i++) {
    00197         /* Don't allow creating new objects over existing.
    00198          * Even if we called the destructor and reused this memory,
    00199          * we don't know whether 'size' and size of currently allocated
    00200          * memory are the same (because of possible inheritance).
    00201          * Use { size_t index = item->index; delete item; new (index) item; }
    00202          * instead to make sure destructor is called and no memory leaks. */
    00203         assert(ptr != Tpool->data[i]);
    00204       }
    00205       return ptr;
    00206     }
    00207
    00208
    00216     static inline bool CanAllocateItem(size_t n = 1)
    00217     {
    00218       return Tpool->CanAllocate(n);
    00219     }
    00220
    00225     static inline bool CleaningPool()
    00226     {
    00227       return Tpool->cleaning;
    00228     }
    00229
    00235     static inline bool IsValidID(size_t index)
    00236     {
    00237       return Tpool->IsValidID(index);
    00238     }
    00239
    00246     static inline Titem *Get(size_t index)
    00247     {
    00248       return Tpool->Get(index);
    00249     }
    00250
    00257     static inline Titem *GetIfValid(size_t index)
    00258     {
    00259       return index < Tpool->first_unused ? Tpool->Get(index) : NULL;
    00260     }
    00261
    00267     static inline size_t GetPoolSize()
    00268     {
    00269       return Tpool->first_unused;
    00270     }
    00271
    00276     static inline size_t GetNumItems()
    00277     {
    00278       return Tpool->items;
    00279     }
    00280
    00288     static inline void PostDestructor(size_t index) { }
    00289   };
    00290
    00291 private:
    00292   static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t);
    00293
    00298   struct AllocCache {
    00300     AllocCache *next;
    00301   };
    00302
    00304   AllocCache *alloc_cache;
    00305
    00306   void *AllocateItem(size_t size, size_t index);
    00307   void ResizeFor(size_t index);
    00308   size_t FindFirstFree();
    00309
    00310   void *GetNew(size_t size);
    00311   void *GetNew(size_t size, size_t index);
    00312
    00313   void FreeItem(size_t index);
    00314 };
    00315
    00316 #define FOR_ALL_ITEMS_FROM(type, iter, var, start) \
    00317   for (size_t iter = start; var = NULL, iter < type::GetPoolSize(); iter++) \
    00318     if ((var = type::Get(iter)) != NULL)
    00319
    00320 #define FOR_ALL_ITEMS(type, iter, var) FOR_ALL_ITEMS_FROM(type, iter, var, 0)
    00321
    00322 #endif /* POOL_TYPE_HPP */