# 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
    00036   bool cleaning;
    00037
    00038   Titem **data;
    00039
    00041   Pool(const char *name);
    00043   void CleanPool();
    00044
    00051   FORCEINLINE Titem *Get(size_t index)
    00052   {
    00053     assert(index < this->first_unused);
    00054     return this->data[index];
    00055   }
    00056
    00062   FORCEINLINE bool IsValidID(size_t index)
    00063   {
    00064     return index < this->first_unused && this->Get(index) != NULL;
    00065   }
    00066
    00072   FORCEINLINE bool CanAllocate(size_t n = 1)
    00073   {
    00074     return this->items <= Tmax_size - n;
    00075   }
    00076
    00081   template <struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tcache, Tzero> *Tpool>
    00082   struct PoolItem {
    00083     Tindex index;
    00084
    00091     FORCEINLINE void *operator new(size_t size)
    00092     {
    00093       return Tpool->GetNew(size);
    00094     }
    00095
    00101     FORCEINLINE void operator delete(void *p)
    00102     {
    00103       Titem *pn = (Titem *)p;
    00104       assert(pn == Tpool->Get(pn->index));
    00105       Tpool->FreeItem(pn->index);
    00106     }
    00107
    00116     FORCEINLINE void *operator new(size_t size, size_t index)
    00117     {
    00118       return Tpool->GetNew(size, index);
    00119     }
    00120
    00129     FORCEINLINE void *operator new(size_t size, void *ptr)
    00130     {
    00131       for (size_t i = 0; i < Tpool->first_unused; i++) {
    00132         /* Don't allow creating new objects over existing.
    00133          * Even if we called the destructor and reused this memory,
    00134          * we don't know whether 'size' and size of currently allocated
    00135          * memory are the same (because of possible inheritance).
    00136          * Use { size_t index = item->index; delete item; new (index) item; }
    00137          * instead to make sure destructor is called and no memory leaks. */
    00138         assert(ptr != Tpool->data[i]);
    00139       }
    00140       return ptr;
    00141     }
    00142
    00143
    00151     static FORCEINLINE bool CanAllocateItem(size_t n = 1)
    00152     {
    00153       return Tpool->CanAllocate(n);
    00154     }
    00155
    00160     static FORCEINLINE bool CleaningPool()
    00161     {
    00162       return Tpool->cleaning;
    00163     }
    00164
    00170     static FORCEINLINE bool IsValidID(size_t index)
    00171     {
    00172       return Tpool->IsValidID(index);
    00173     }
    00174
    00181     static FORCEINLINE Titem *Get(size_t index)
    00182     {
    00183       return Tpool->Get(index);
    00184     }
    00185
    00192     static FORCEINLINE Titem *GetIfValid(size_t index)
    00193     {
    00194       return index < Tpool->first_unused ? Tpool->Get(index) : NULL;
    00195     }
    00196
    00202     static FORCEINLINE size_t GetPoolSize()
    00203     {
    00204       return Tpool->first_unused;
    00205     }
    00206
    00211     static FORCEINLINE size_t GetNumItems()
    00212     {
    00213       return Tpool->items;
    00214     }
    00215
    00223     static FORCEINLINE void PostDestructor(size_t index) { }
    00224   };
    00225
    00226 private:
    00227   static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t);
    00228
    00233   struct AllocCache {
    00235     AllocCache *next;
    00236   };
    00237
    00239   AllocCache *alloc_cache;
    00240
    00248   void *AllocateItem(size_t size, size_t index);
    00249
    00256   void ResizeFor(size_t index);
    00257
    00262   size_t FindFirstFree();
    00263
    00270   void *GetNew(size_t size);
    00271
    00279   void *GetNew(size_t size, size_t index);
    00280
    00287   void FreeItem(size_t index);
    00288 };
    00289
    00290 #define FOR_ALL_ITEMS_FROM(type, iter, var, start) \
    00291   for (size_t iter = start; var = NULL, iter < type::GetPoolSize(); iter++) \
    00292     if ((var = type::Get(iter)) != NULL)
    00293
    00294 #define FOR_ALL_ITEMS(type, iter, var) FOR_ALL_ITEMS_FROM(type, iter, var, 0)
    00295
    00296 #endif /* POOL_TYPE_HPP */