# 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
    00025 template <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size, bool Tcache = false, bool Tzero = true>
    00026 struct Pool {
    00027   static const size_t MAX_SIZE = Tmax_size;
    00028
    00029   const char * const name;
    00030
    00031   size_t size;
    00032   size_t first_free;
    00033   size_t first_unused;
    00034   size_t items;
    00035   bool cleaning;
    00036
    00037   Titem **data;
    00038
    00039   Pool(const char *name);
    00040   void CleanPool();
    00041
    00048   FORCEINLINE Titem *Get(size_t index)
    00049   {
    00050     assert(index < this->first_unused);
    00051     return this->data[index];
    00052   }
    00053
    00059   FORCEINLINE bool IsValidID(size_t index)
    00060   {
    00061     return index < this->first_unused && this->Get(index) != NULL;
    00062   }
    00063
    00069   FORCEINLINE bool CanAllocate(size_t n = 1)
    00070   {
    00071     return this->items <= Tmax_size - n;
    00072   }
    00073
    00078   template <struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tcache, Tzero> *Tpool>
    00079   struct PoolItem {
    00080     Tindex index;
    00081
    00088     FORCEINLINE void *operator new(size_t size)
    00089     {
    00090       return Tpool->GetNew(size);
    00091     }
    00092
    00098     FORCEINLINE void operator delete(void *p)
    00099     {
    00100       Titem *pn = (Titem *)p;
    00101       assert(pn == Tpool->Get(pn->index));
    00102       Tpool->FreeItem(pn->index);
    00103     }
    00104
    00113     FORCEINLINE void *operator new(size_t size, size_t index)
    00114     {
    00115       return Tpool->GetNew(size, index);
    00116     }
    00117
    00126     FORCEINLINE void *operator new(size_t size, void *ptr)
    00127     {
    00128       for (size_t i = 0; i < Tpool->first_unused; i++) {
    00129         /* Don't allow creating new objects over existing.
    00130          * Even if we called the destructor and reused this memory,
    00131          * we don't know whether 'size' and size of currently allocated
    00132          * memory are the same (because of possible inheritance).
    00133          * Use { size_t index = item->index; delete item; new (index) item; }
    00134          * instead to make sure destructor is called and no memory leaks. */
    00135         assert(ptr != Tpool->data[i]);
    00136       }
    00137       return ptr;
    00138     }
    00139
    00140
    00148     static FORCEINLINE bool CanAllocateItem(size_t n = 1)
    00149     {
    00150       return Tpool->CanAllocate(n);
    00151     }
    00152
    00157     static FORCEINLINE bool CleaningPool()
    00158     {
    00159       return Tpool->cleaning;
    00160     }
    00161
    00167     static FORCEINLINE bool IsValidID(size_t index)
    00168     {
    00169       return Tpool->IsValidID(index);
    00170     }
    00171
    00178     static FORCEINLINE Titem *Get(size_t index)
    00179     {
    00180       return Tpool->Get(index);
    00181     }
    00182
    00189     static FORCEINLINE Titem *GetIfValid(size_t index)
    00190     {
    00191       return index < Tpool->first_unused ? Tpool->Get(index) : NULL;
    00192     }
    00193
    00199     static FORCEINLINE size_t GetPoolSize()
    00200     {
    00201       return Tpool->first_unused;
    00202     }
    00203
    00208     static FORCEINLINE size_t GetNumItems()
    00209     {
    00210       return Tpool->items;
    00211     }
    00212
    00220     static FORCEINLINE void PostDestructor(size_t index) { }
    00221   };
    00222
    00223 private:
    00224   static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t);
    00225
    00230   struct AllocCache {
    00232     AllocCache *next;
    00233   };
    00234
    00236   AllocCache *alloc_cache;
    00237
    00238   void *AllocateItem(size_t size, size_t index);
    00239   void ResizeFor(size_t index);
    00240   size_t FindFirstFree();
    00241
    00242   void *GetNew(size_t size);
    00243   void *GetNew(size_t size, size_t index);
    00244
    00245   void FreeItem(size_t index);
    00246 };
    00247
    00248 #define FOR_ALL_ITEMS_FROM(type, iter, var, start) \
    00249   for (size_t iter = start; var = NULL, iter < type::GetPoolSize(); iter++) \
    00250     if ((var = type::Get(iter)) != NULL)
    00251
    00252 #define FOR_ALL_ITEMS(type, iter, var) FOR_ALL_ITEMS_FROM(type, iter, var, 0)
    00253
    00254 #endif /* POOL_TYPE_HPP */