# pool_type.hpp

Go to the documentation of this file.

    00001 /* $Id: pool_type.hpp 24900 2013-01-08 22:46:42Z planetmaker $ */
    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   inline Titem *Get(size_t index)
    00102   {
    00103     assert(index < this->first_unused);
    00104     return this->data[index];
    00105   }
    00106
    00112   inline bool IsValidID(size_t index)
    00113   {
    00114     return index < this->first_unused && this->Get(index) != NULL;
    00115   }
    00116
    00122   inline 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     inline void *operator new(size_t size)
    00146     {
    00147       return Tpool->GetNew(size);
    00148     }
    00149
    00155     inline 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     inline void *operator new(size_t size, size_t index)
    00171     {
    00172       return Tpool->GetNew(size, index);
    00173     }
    00174
    00183     inline 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 inline bool CanAllocateItem(size_t n = 1)
    00206     {
    00207       return Tpool->CanAllocate(n);
    00208     }
    00209
    00214     static inline bool CleaningPool()
    00215     {
    00216       return Tpool->cleaning;
    00217     }
    00218
    00224     static inline bool IsValidID(size_t index)
    00225     {
    00226       return Tpool->IsValidID(index);
    00227     }
    00228
    00235     static inline Titem *Get(size_t index)
    00236     {
    00237       return Tpool->Get(index);
    00238     }
    00239
    00246     static inline Titem *GetIfValid(size_t index)
    00247     {
    00248       return index < Tpool->first_unused ? Tpool->Get(index) : NULL;
    00249     }
    00250
    00256     static inline size_t GetPoolSize()
    00257     {
    00258       return Tpool->first_unused;
    00259     }
    00260
    00265     static inline size_t GetNumItems()
    00266     {
    00267       return Tpool->items;
    00268     }
    00269
    00277     static inline 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 */