OpenTTD Source  14.0-beta1
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 "enum_type.hpp"
14 
16 enum PoolType {
17  PT_NONE = 0x00,
18  PT_NORMAL = 0x01,
19  PT_NCLIENT = 0x02,
20  PT_NADMIN = 0x04,
21  PT_DATA = 0x08,
22  PT_ALL = 0x0F,
23 };
25 
26 typedef std::vector<struct PoolBase *> PoolVector;
27 
29 struct PoolBase {
30  const PoolType type;
31 
36  static PoolVector *GetPools()
37  {
38  static PoolVector *pools = new PoolVector();
39  return pools;
40  }
41 
42  static void Clean(PoolType);
43 
48  PoolBase(PoolType pt) : type(pt)
49  {
50  PoolBase::GetPools()->push_back(this);
51  }
52 
53  virtual ~PoolBase();
54 
58  virtual void CleanPool() = 0;
59 
60 private:
65  PoolBase(const PoolBase &other);
66 };
67 
79 template <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size, PoolType Tpool_type = PT_NORMAL, bool Tcache = false, bool Tzero = true>
80 struct Pool : PoolBase {
81  /* Ensure Tmax_size is within the bounds of Tindex. */
82  static_assert((uint64_t)(Tmax_size - 1) >> 8 * sizeof(Tindex) == 0);
83 
84  static constexpr size_t MAX_SIZE = Tmax_size;
85 
86  const char * const name;
87 
88  size_t size;
89  size_t first_free;
90  size_t first_unused;
91  size_t items;
92 #ifdef WITH_ASSERT
93  size_t checked;
94 #endif /* WITH_ASSERT */
95  bool cleaning;
96 
97  Titem **data;
98 
99  Pool(const char *name);
100  void CleanPool() override;
101 
108  inline Titem *Get(size_t index)
109  {
110  assert(index < this->first_unused);
111  return this->data[index];
112  }
113 
119  inline bool IsValidID(size_t index)
120  {
121  return index < this->first_unused && this->Get(index) != nullptr;
122  }
123 
129  inline bool CanAllocate(size_t n = 1)
130  {
131  bool ret = this->items <= Tmax_size - n;
132 #ifdef WITH_ASSERT
133  this->checked = ret ? n : 0;
134 #endif /* WITH_ASSERT */
135  return ret;
136  }
137 
142  template <class T>
143  struct PoolIterator {
144  typedef T value_type;
145  typedef T *pointer;
146  typedef T &reference;
147  typedef size_t difference_type;
148  typedef std::forward_iterator_tag iterator_category;
149 
150  explicit PoolIterator(size_t index) : index(index)
151  {
152  this->ValidateIndex();
153  };
154 
155  bool operator==(const PoolIterator &other) const { return this->index == other.index; }
156  bool operator!=(const PoolIterator &other) const { return !(*this == other); }
157  T * operator*() const { return T::Get(this->index); }
158  PoolIterator & operator++() { this->index++; this->ValidateIndex(); return *this; }
159 
160  private:
161  size_t index;
162  void ValidateIndex()
163  {
164  while (this->index < T::GetPoolSize() && !(T::IsValidID(this->index))) this->index++;
165  if (this->index >= T::GetPoolSize()) this->index = T::Pool::MAX_SIZE;
166  }
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  IterateWrapper(size_t from = 0) : from(from) {}
177  PoolIterator<T> begin() { return PoolIterator<T>(this->from); }
178  PoolIterator<T> end() { return PoolIterator<T>(T::Pool::MAX_SIZE); }
179  bool empty() { return this->begin() == this->end(); }
180  };
181 
186  template <class T, class F>
188  typedef T value_type;
189  typedef T *pointer;
190  typedef T &reference;
191  typedef size_t difference_type;
192  typedef std::forward_iterator_tag iterator_category;
193 
194  explicit PoolIteratorFiltered(size_t index, F filter) : index(index), filter(filter)
195  {
196  this->ValidateIndex();
197  };
198 
199  bool operator==(const PoolIteratorFiltered &other) const { return this->index == other.index; }
200  bool operator!=(const PoolIteratorFiltered &other) const { return !(*this == other); }
201  T * operator*() const { return T::Get(this->index); }
202  PoolIteratorFiltered & operator++() { this->index++; this->ValidateIndex(); return *this; }
203 
204  private:
205  size_t index;
206  F filter;
207  void ValidateIndex()
208  {
209  while (this->index < T::GetPoolSize() && !(T::IsValidID(this->index) && this->filter(this->index))) this->index++;
210  if (this->index >= T::GetPoolSize()) this->index = T::Pool::MAX_SIZE;
211  }
212  };
213 
214  /*
215  * Iterable ensemble of all valid T
216  * @tparam T Type of the class/struct that is going to be iterated
217  */
218  template <class T, class F>
220  size_t from;
221  F filter;
222  IterateWrapperFiltered(size_t from, F filter) : from(from), filter(filter) {}
223  PoolIteratorFiltered<T, F> begin() { return PoolIteratorFiltered<T, F>(this->from, this->filter); }
224  PoolIteratorFiltered<T, F> end() { return PoolIteratorFiltered<T, F>(T::Pool::MAX_SIZE, this->filter); }
225  bool empty() { return this->begin() == this->end(); }
226  };
227 
232  template <struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero> *Tpool>
233  struct PoolItem {
234  Tindex index;
235 
237  typedef struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero> Pool;
238 
245  inline void *operator new(size_t size)
246  {
247  return Tpool->GetNew(size);
248  }
249 
255  inline void operator delete(void *p)
256  {
257  if (p == nullptr) return;
258  Titem *pn = (Titem *)p;
259  assert(pn == Tpool->Get(pn->index));
260  Tpool->FreeItem(pn->index);
261  }
262 
271  inline void *operator new(size_t size, size_t index)
272  {
273  return Tpool->GetNew(size, index);
274  }
275 
283  inline void *operator new(size_t, void *ptr)
284  {
285  for (size_t i = 0; i < Tpool->first_unused; i++) {
286  /* Don't allow creating new objects over existing.
287  * Even if we called the destructor and reused this memory,
288  * we don't know whether 'size' and size of currently allocated
289  * memory are the same (because of possible inheritance).
290  * Use { size_t index = item->index; delete item; new (index) item; }
291  * instead to make sure destructor is called and no memory leaks. */
292  assert(ptr != Tpool->data[i]);
293  }
294  return ptr;
295  }
296 
297 
305  static inline bool CanAllocateItem(size_t n = 1)
306  {
307  return Tpool->CanAllocate(n);
308  }
309 
314  static inline bool CleaningPool()
315  {
316  return Tpool->cleaning;
317  }
318 
324  static inline bool IsValidID(size_t index)
325  {
326  return Tpool->IsValidID(index);
327  }
328 
335  static inline Titem *Get(size_t index)
336  {
337  return Tpool->Get(index);
338  }
339 
346  static inline Titem *GetIfValid(size_t index)
347  {
348  return index < Tpool->first_unused ? Tpool->Get(index) : nullptr;
349  }
350 
356  static inline size_t GetPoolSize()
357  {
358  return Tpool->first_unused;
359  }
360 
365  static inline size_t GetNumItems()
366  {
367  return Tpool->items;
368  }
369 
377  static inline void PostDestructor([[maybe_unused]] size_t index) { }
378 
384  static Pool::IterateWrapper<Titem> Iterate(size_t from = 0) { return Pool::IterateWrapper<Titem>(from); }
385  };
386 
387 private:
388  static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t);
389 
394  struct AllocCache {
397  };
398 
401 
402  void *AllocateItem(size_t size, size_t index);
403  void ResizeFor(size_t index);
404  size_t FindFirstFree();
405 
406  void *GetNew(size_t size);
407  void *GetNew(size_t size, size_t index);
408 
409  void FreeItem(size_t index);
410 };
411 
412 #endif /* POOL_TYPE_HPP */
Pool::IsValidID
bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:119
PoolVector
std::vector< struct PoolBase * > PoolVector
Vector of pointers to PoolBase.
Definition: pool_type.hpp:26
Pool::PoolItem::Get
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:335
Pool::PoolItem::GetIfValid
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:346
Pool::AllocCache
Helper struct to cache 'freed' PoolItems so we do not need to allocate them again.
Definition: pool_type.hpp:394
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition: pool_type.hpp:234
Pool::IterateWrapperFiltered
Definition: pool_type.hpp:219
Pool::PoolIterator
Iterator to iterate all valid T of a pool.
Definition: pool_type.hpp:143
Pool::MAX_SIZE
static constexpr size_t MAX_SIZE
Make template parameter accessible from outside.
Definition: pool_type.hpp:84
PoolBase
Base class for base of all pools.
Definition: pool_type.hpp:29
Pool::PoolItem::GetPoolSize
static size_t GetPoolSize()
Returns first unused index.
Definition: pool_type.hpp:356
Pool::alloc_cache
AllocCache * alloc_cache
Cache of freed pointers.
Definition: pool_type.hpp:400
Pool::items
size_t items
Number of used indexes (non-nullptr)
Definition: pool_type.hpp:91
Pool::PoolItem::PostDestructor
static void PostDestructor([[maybe_unused]] size_t index)
Dummy function called after destructor of each member.
Definition: pool_type.hpp:377
Pool::data
Titem ** data
Pointer to array of pointers to Titem.
Definition: pool_type.hpp:97
PoolType
PoolType
Various types of a pool.
Definition: pool_type.hpp:16
Pool::IterateWrapper
Definition: pool_type.hpp:174
Pool::cleaning
bool cleaning
True if cleaning pool (deleting all items)
Definition: pool_type.hpp:95
PT_NADMIN
@ PT_NADMIN
Network admin pool.
Definition: pool_type.hpp:20
PT_NONE
@ PT_NONE
No pool is selected.
Definition: pool_type.hpp:17
Pool::CleanPool
void CleanPool() override
Virtual method that deletes all items in the pool.
Pool::PoolIteratorFiltered
Iterator to iterate all valid T of a pool.
Definition: pool_type.hpp:187
Pool::NO_FREE_ITEM
static const size_t NO_FREE_ITEM
Constant to indicate we can't allocate any more items.
Definition: pool_type.hpp:388
Pool::Get
Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:108
PT_NCLIENT
@ PT_NCLIENT
Network client pools.
Definition: pool_type.hpp:19
Pool::first_free
size_t first_free
No item with index lower than this is free (doesn't say anything about this one!)
Definition: pool_type.hpp:89
PT_ALL
@ PT_ALL
All pool types.
Definition: pool_type.hpp:22
Pool::PoolItem::Iterate
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:384
PT_NORMAL
@ PT_NORMAL
Normal pool containing game objects.
Definition: pool_type.hpp:18
Pool
Base class for all pools.
Definition: pool_type.hpp:80
Pool::size
size_t size
Current allocated size.
Definition: pool_type.hpp:88
PT_DATA
@ PT_DATA
NewGRF or other data, that is not reset together with normal pools.
Definition: pool_type.hpp:21
Pool::PoolItem::GetNumItems
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:365
Pool::AllocCache::next
AllocCache * next
The next in our 'cache'.
Definition: pool_type.hpp:396
Pool::PoolItem::CleaningPool
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
Definition: pool_type.hpp:314
Pool::PoolItem::CanAllocateItem
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:305
MAX_UVALUE
#define MAX_UVALUE(type)
The largest value that can be entered in a variable.
Definition: stdafx.h:388
enum_type.hpp
DECLARE_ENUM_AS_BIT_SET
DECLARE_ENUM_AS_BIT_SET(GenderEthnicity) enum CompanyManagerFaceVariable
Bitgroups of the CompanyManagerFace variable.
Definition: company_manager_face.h:29
PoolBase::PoolBase
PoolBase(PoolType pt)
Constructor registers this object in the pool vector.
Definition: pool_type.hpp:48
Pool::name
const char *const name
Name of this pool.
Definition: pool_type.hpp:86
Pool::first_unused
size_t first_unused
This and all higher indexes are free (doesn't say anything about first_unused-1 !)
Definition: pool_type.hpp:90
Pool::PoolItem::IsValidID
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:324
PoolBase::type
const PoolType type
Type of this pool.
Definition: pool_type.hpp:30
Pool::PoolItem
Base class for all PoolItems.
Definition: pool_type.hpp:233
PoolBase::GetPools
static PoolVector * GetPools()
Function used to access the vector of all pools.
Definition: pool_type.hpp:36
Pool::CanAllocate
bool CanAllocate(size_t n=1)
Tests whether we can allocate 'n' items.
Definition: pool_type.hpp:129