OpenTTD
pool_type.hpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * 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.
4  * 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.
5  * 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/>.
6  */
7 
10 #ifndef POOL_TYPE_HPP
11 #define POOL_TYPE_HPP
12 
13 #include "smallvec_type.hpp"
14 #include "enum_type.hpp"
15 #include <functional>
16 
18 enum PoolType {
19  PT_NONE = 0x00,
20  PT_NORMAL = 0x01,
21  PT_NCLIENT = 0x02,
22  PT_NADMIN = 0x04,
23  PT_DATA = 0x08,
24  PT_ALL = 0x0F,
25 };
27 
28 typedef std::vector<struct PoolBase *> PoolVector;
29 
31 struct PoolBase {
32  const PoolType type;
33 
38  static PoolVector *GetPools()
39  {
40  static PoolVector *pools = new PoolVector();
41  return pools;
42  }
43 
44  static void Clean(PoolType);
45 
50  PoolBase(PoolType pt) : type(pt)
51  {
52  PoolBase::GetPools()->push_back(this);
53  }
54 
55  virtual ~PoolBase();
56 
60  virtual void CleanPool() = 0;
61 
62 private:
67  PoolBase(const PoolBase &other);
68 };
69 
81 template <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size, PoolType Tpool_type = PT_NORMAL, bool Tcache = false, bool Tzero = true>
82 struct Pool : PoolBase {
83  /* Ensure Tmax_size is within the bounds of Tindex. */
84  assert_compile((uint64)(Tmax_size - 1) >> 8 * sizeof(Tindex) == 0);
85 
86  static const size_t MAX_SIZE = Tmax_size;
87 
88  const char * const name;
89 
90  size_t size;
91  size_t first_free;
92  size_t first_unused;
93  size_t items;
94 #ifdef OTTD_ASSERT
95  size_t checked;
96 #endif /* OTTD_ASSERT */
97  bool cleaning;
98 
99  Titem **data;
100 
101  Pool(const char *name);
102  virtual void CleanPool();
103 
110  inline Titem *Get(size_t index)
111  {
112  assert(index < this->first_unused);
113  return this->data[index];
114  }
115 
121  inline bool IsValidID(size_t index)
122  {
123  return index < this->first_unused && this->Get(index) != nullptr;
124  }
125 
131  inline bool CanAllocate(size_t n = 1)
132  {
133  bool ret = this->items <= Tmax_size - n;
134 #ifdef OTTD_ASSERT
135  this->checked = ret ? n : 0;
136 #endif /* OTTD_ASSERT */
137  return ret;
138  }
139 
144  template <class T>
145  struct PoolIterator {
146  typedef T value_type;
147  typedef T* pointer;
148  typedef T& reference;
149  typedef size_t difference_type;
150  typedef std::forward_iterator_tag iterator_category;
151 
152  explicit PoolIterator(size_t index, std::function<bool(size_t)> filter = nullptr) : index(index), filter(filter)
153  {
154  if (this->filter == nullptr) this->filter = [](size_t) { return true; };
155  this->ValidateIndex();
156  };
157 
158  bool operator==(const PoolIterator &other) const { return this->index == other.index; }
159  bool operator!=(const PoolIterator &other) const { return !(*this == other); }
160  T * operator*() const { return T::Get(this->index); }
161  PoolIterator & operator++() { this->index++; this->ValidateIndex(); return *this; }
162 
163  private:
164  size_t index;
165  std::function<bool(size_t)> filter;
166  void ValidateIndex() { while (this->index < T::GetPoolSize() && !(T::IsValidID(this->index) && this->filter(this->index))) this->index++; }
167  };
168 
169  /*
170  * Iterable ensemble of all valid T
171  * @tparam T Type of the class/struct that is going to be iterated
172  */
173  template <class T>
174  struct IterateWrapper {
175  size_t from;
176  std::function<bool(size_t)> filter;
177  IterateWrapper(size_t from = 0, std::function<bool(size_t)> filter = nullptr) : from(from), filter(filter) {}
178  PoolIterator<T> begin() { return PoolIterator<T>(this->from, this->filter); }
179  PoolIterator<T> end() { return PoolIterator<T>(T::GetPoolSize()); }
180  bool empty() { return this->begin() == this->end(); }
181  };
182 
187  template <struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero> *Tpool>
188  struct PoolItem {
189  Tindex index;
190 
192  typedef struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero> Pool;
193 
200  inline void *operator new(size_t size)
201  {
202  return Tpool->GetNew(size);
203  }
204 
210  inline void operator delete(void *p)
211  {
212  if (p == nullptr) return;
213  Titem *pn = (Titem *)p;
214  assert(pn == Tpool->Get(pn->index));
215  Tpool->FreeItem(pn->index);
216  }
217 
226  inline void *operator new(size_t size, size_t index)
227  {
228  return Tpool->GetNew(size, index);
229  }
230 
239  inline void *operator new(size_t size, void *ptr)
240  {
241  for (size_t i = 0; i < Tpool->first_unused; i++) {
242  /* Don't allow creating new objects over existing.
243  * Even if we called the destructor and reused this memory,
244  * we don't know whether 'size' and size of currently allocated
245  * memory are the same (because of possible inheritance).
246  * Use { size_t index = item->index; delete item; new (index) item; }
247  * instead to make sure destructor is called and no memory leaks. */
248  assert(ptr != Tpool->data[i]);
249  }
250  return ptr;
251  }
252 
253 
261  static inline bool CanAllocateItem(size_t n = 1)
262  {
263  return Tpool->CanAllocate(n);
264  }
265 
270  static inline bool CleaningPool()
271  {
272  return Tpool->cleaning;
273  }
274 
280  static inline bool IsValidID(size_t index)
281  {
282  return Tpool->IsValidID(index);
283  }
284 
291  static inline Titem *Get(size_t index)
292  {
293  return Tpool->Get(index);
294  }
295 
302  static inline Titem *GetIfValid(size_t index)
303  {
304  return index < Tpool->first_unused ? Tpool->Get(index) : nullptr;
305  }
306 
312  static inline size_t GetPoolSize()
313  {
314  return Tpool->first_unused;
315  }
316 
321  static inline size_t GetNumItems()
322  {
323  return Tpool->items;
324  }
325 
333  static inline void PostDestructor(size_t index) { }
334 
340  static Pool::IterateWrapper<Titem> Iterate(size_t from = 0) { return Pool::IterateWrapper<Titem>(from); }
341  };
342 
343 private:
344  static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t);
345 
350  struct AllocCache {
353  };
354 
357 
358  void *AllocateItem(size_t size, size_t index);
359  void ResizeFor(size_t index);
360  size_t FindFirstFree();
361 
362  void *GetNew(size_t size);
363  void *GetNew(size_t size, size_t index);
364 
365  void FreeItem(size_t index);
366 };
367 
368 #endif /* POOL_TYPE_HPP */
size_t first_unused
This and all higher indexes are free (doesn&#39;t say anything about first_unused-1 !) ...
Definition: pool_type.hpp:92
All pool types.
Definition: pool_type.hpp:24
DECLARE_ENUM_AS_BIT_SET(GenderEthnicity) enum CompanyManagerFaceVariable
Bitgroups of the CompanyManagerFace variable.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:302
Simple vector class that allows allocating an item without the need to copy this->data needlessly...
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:291
static PoolVector * GetPools()
Function used to access the vector of all pools.
Definition: pool_type.hpp:38
bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:121
Base class for base of all pools.
Definition: pool_type.hpp:31
Tindex index
Index of this pool item.
Definition: pool_type.hpp:189
Iterator to iterate all valid T of a pool.
Definition: pool_type.hpp:145
AllocCache * alloc_cache
Cache of freed pointers.
Definition: pool_type.hpp:356
Normal pool containing game objects.
Definition: pool_type.hpp:20
Type (helpers) for enums.
Network client pools.
Definition: pool_type.hpp:21
static const size_t MAX_SIZE
Make template parameter accessible from outside.
Definition: pool_type.hpp:86
static void PostDestructor(size_t index)
Dummy function called after destructor of each member.
Definition: pool_type.hpp:333
static size_t GetPoolSize()
Returns first unused index.
Definition: pool_type.hpp:312
Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:110
static const size_t NO_FREE_ITEM
Constant to indicate we can&#39;t allocate any more items.
Definition: pool_type.hpp:344
PoolBase(PoolType pt)
Constructor registers this object in the pool vector.
Definition: pool_type.hpp:50
Helper struct to cache &#39;freed&#39; PoolItems so we do not need to allocate them again.
Definition: pool_type.hpp:350
bool cleaning
True if cleaning pool (deleting all items)
Definition: pool_type.hpp:97
NewGRF or other data, that is not reset together with normal pools.
Definition: pool_type.hpp:23
Titem ** data
Pointer to array of pointers to Titem.
Definition: pool_type.hpp:99
size_t items
Number of used indexes (non-nullptr)
Definition: pool_type.hpp:93
#define MAX_UVALUE(type)
The largest value that can be entered in a variable.
Definition: stdafx.h:469
AllocCache * next
The next in our &#39;cache&#39;.
Definition: pool_type.hpp:352
Base class for all PoolItems.
Definition: pool_type.hpp:188
Base class for all pools.
Definition: pool_type.hpp:82
size_t first_free
No item with index lower than this is free (doesn&#39;t say anything about this one!) ...
Definition: pool_type.hpp:91
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
Definition: pool_type.hpp:270
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:340
PoolType
Various types of a pool.
Definition: pool_type.hpp:18
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:321
No pool is selected.
Definition: pool_type.hpp:19
std::vector< struct PoolBase * > PoolVector
Vector of pointers to PoolBase.
Definition: pool_type.hpp:28
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:261
bool CanAllocate(size_t n=1)
Tests whether we can allocate &#39;n&#39; items.
Definition: pool_type.hpp:131
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:280
size_t size
Current allocated size.
Definition: pool_type.hpp:90
Network admin pool.
Definition: pool_type.hpp:22
const char *const name
Name of this pool.
Definition: pool_type.hpp:88
const PoolType type
Type of this pool.
Definition: pool_type.hpp:32
virtual void CleanPool()
Virtual method that deletes all items in the pool.