Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
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
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
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
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
00198
00199
00200
00201
00202
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