# pool_type.hpp

Go to the documentation of this file.

    00001 /* $Id: pool_type.hpp 25887 2013-10-20 13:35:35Z fonsinchen $ */
    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   static const size_t MAX_SIZE = Tmax_size;
    00085
    00086   const char * const name;
    00087
    00088   size_t size;
    00089   size_t first_free;
    00090   size_t first_unused;
    00091   size_t items;
    00092 #ifdef OTTD_ASSERT
    00093   size_t checked;
    00094 #endif /* OTTD_ASSERT */
    00095   bool cleaning;
    00096
    00097   Titem **data;
    00098
    00099   Pool(const char *name);
    00100   virtual void CleanPool();
    00101
    00108   inline Titem *Get(size_t index)
    00109   {
    00110     assert(index < this->first_unused);
    00111     return this->data[index];
    00112   }
    00113
    00119   inline bool IsValidID(size_t index)
    00120   {
    00121     return index < this->first_unused && this->Get(index) != NULL;
    00122   }
    00123
    00129   inline bool CanAllocate(size_t n = 1)
    00130   {
    00131     bool ret = this->items <= Tmax_size - n;
    00132 #ifdef OTTD_ASSERT
    00133     this->checked = ret ? n : 0;
    00134 #endif /* OTTD_ASSERT */
    00135     return ret;
    00136   }
    00137
    00142   template <struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero> *Tpool>
    00143   struct PoolItem {
    00144     Tindex index;
    00145
    00152     inline void *operator new(size_t size)
    00153     {
    00154       return Tpool->GetNew(size);
    00155     }
    00156
    00162     inline void operator delete(void *p)
    00163     {
    00164       if (p == NULL) return;
    00165       Titem *pn = (Titem *)p;
    00166       assert(pn == Tpool->Get(pn->index));
    00167       Tpool->FreeItem(pn->index);
    00168     }
    00169
    00178     inline void *operator new(size_t size, size_t index)
    00179     {
    00180       return Tpool->GetNew(size, index);
    00181     }
    00182
    00191     inline void *operator new(size_t size, void *ptr)
    00192     {
    00193       for (size_t i = 0; i < Tpool->first_unused; i++) {
    00194         /* Don't allow creating new objects over existing.
    00195          * Even if we called the destructor and reused this memory,
    00196          * we don't know whether 'size' and size of currently allocated
    00197          * memory are the same (because of possible inheritance).
    00198          * Use { size_t index = item->index; delete item; new (index) item; }
    00199          * instead to make sure destructor is called and no memory leaks. */
    00200         assert(ptr != Tpool->data[i]);
    00201       }
    00202       return ptr;
    00203     }
    00204
    00205
    00213     static inline bool CanAllocateItem(size_t n = 1)
    00214     {
    00215       return Tpool->CanAllocate(n);
    00216     }
    00217
    00222     static inline bool CleaningPool()
    00223     {
    00224       return Tpool->cleaning;
    00225     }
    00226
    00232     static inline bool IsValidID(size_t index)
    00233     {
    00234       return Tpool->IsValidID(index);
    00235     }
    00236
    00243     static inline Titem *Get(size_t index)
    00244     {
    00245       return Tpool->Get(index);
    00246     }
    00247
    00254     static inline Titem *GetIfValid(size_t index)
    00255     {
    00256       return index < Tpool->first_unused ? Tpool->Get(index) : NULL;
    00257     }
    00258
    00264     static inline size_t GetPoolSize()
    00265     {
    00266       return Tpool->first_unused;
    00267     }
    00268
    00273     static inline size_t GetNumItems()
    00274     {
    00275       return Tpool->items;
    00276     }
    00277
    00285     static inline void PostDestructor(size_t index) { }
    00286   };
    00287
    00288 private:
    00289   static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t);
    00290
    00295   struct AllocCache {
    00297     AllocCache *next;
    00298   };
    00299
    00301   AllocCache *alloc_cache;
    00302
    00303   void *AllocateItem(size_t size, size_t index);
    00304   void ResizeFor(size_t index);
    00305   size_t FindFirstFree();
    00306
    00307   void *GetNew(size_t size);
    00308   void *GetNew(size_t size, size_t index);
    00309
    00310   void FreeItem(size_t index);
    00311 };
    00312
    00313 #define FOR_ALL_ITEMS_FROM(type, iter, var, start) \
    00314   for (size_t iter = start; var = NULL, iter < type::GetPoolSize(); iter++) \
    00315     if ((var = type::Get(iter)) != NULL)
    00316
    00317 #define FOR_ALL_ITEMS(type, iter, var) FOR_ALL_ITEMS_FROM(type, iter, var, 0)
    00318
    00319 #endif /* POOL_TYPE_HPP */