OpenTTD Source  20241108-master-g80f628063a
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 the highest possible index, i.e. Tmax_size -1, is within the bounds of Tindex. */
82  static_assert(Tmax_size - 1 <= MAX_UVALUE(Tindex));
83 
84  static constexpr size_t MAX_SIZE = Tmax_size;
85 
86  using BitmapStorage = size_t;
87  static constexpr size_t BITMAP_SIZE = std::numeric_limits<BitmapStorage>::digits;
88 
89  const char * const name;
90 
91  size_t size;
92  size_t first_free;
93  size_t first_unused;
94  size_t items;
95 #ifdef WITH_ASSERT
96  size_t checked;
97 #endif /* WITH_ASSERT */
98  bool cleaning;
99 
100  Titem **data;
101  std::vector<BitmapStorage> used_bitmap;
102 
103  Pool(const char *name);
104  void CleanPool() override;
105 
112  inline Titem *Get(size_t index)
113  {
114  assert(index < this->first_unused);
115  return this->data[index];
116  }
117 
123  inline bool IsValidID(size_t index)
124  {
125  return index < this->first_unused && this->Get(index) != nullptr;
126  }
127 
133  inline bool CanAllocate(size_t n = 1)
134  {
135  bool ret = this->items <= Tmax_size - n;
136 #ifdef WITH_ASSERT
137  this->checked = ret ? n : 0;
138 #endif /* WITH_ASSERT */
139  return ret;
140  }
141 
146  template <class T>
147  struct PoolIterator {
148  typedef T value_type;
149  typedef T *pointer;
150  typedef T &reference;
151  typedef size_t difference_type;
152  typedef std::forward_iterator_tag iterator_category;
153 
154  explicit PoolIterator(size_t index) : index(index)
155  {
156  this->ValidateIndex();
157  };
158 
159  bool operator==(const PoolIterator &other) const { return this->index == other.index; }
160  bool operator!=(const PoolIterator &other) const { return !(*this == other); }
161  T * operator*() const { return T::Get(this->index); }
162  PoolIterator & operator++() { this->index++; this->ValidateIndex(); return *this; }
163 
164  private:
165  size_t index;
166  void ValidateIndex()
167  {
168  while (this->index < T::GetPoolSize() && !(T::IsValidID(this->index))) this->index++;
169  if (this->index >= T::GetPoolSize()) this->index = T::Pool::MAX_SIZE;
170  }
171  };
172 
173  /*
174  * Iterable ensemble of all valid T
175  * @tparam T Type of the class/struct that is going to be iterated
176  */
177  template <class T>
178  struct IterateWrapper {
179  size_t from;
180  IterateWrapper(size_t from = 0) : from(from) {}
181  PoolIterator<T> begin() { return PoolIterator<T>(this->from); }
182  PoolIterator<T> end() { return PoolIterator<T>(T::Pool::MAX_SIZE); }
183  bool empty() { return this->begin() == this->end(); }
184  };
185 
190  template <class T, class F>
192  typedef T value_type;
193  typedef T *pointer;
194  typedef T &reference;
195  typedef size_t difference_type;
196  typedef std::forward_iterator_tag iterator_category;
197 
198  explicit PoolIteratorFiltered(size_t index, F filter) : index(index), filter(filter)
199  {
200  this->ValidateIndex();
201  };
202 
203  bool operator==(const PoolIteratorFiltered &other) const { return this->index == other.index; }
204  bool operator!=(const PoolIteratorFiltered &other) const { return !(*this == other); }
205  T * operator*() const { return T::Get(this->index); }
206  PoolIteratorFiltered & operator++() { this->index++; this->ValidateIndex(); return *this; }
207 
208  private:
209  size_t index;
210  F filter;
211  void ValidateIndex()
212  {
213  while (this->index < T::GetPoolSize() && !(T::IsValidID(this->index) && this->filter(this->index))) this->index++;
214  if (this->index >= T::GetPoolSize()) this->index = T::Pool::MAX_SIZE;
215  }
216  };
217 
218  /*
219  * Iterable ensemble of all valid T
220  * @tparam T Type of the class/struct that is going to be iterated
221  */
222  template <class T, class F>
224  size_t from;
225  F filter;
226  IterateWrapperFiltered(size_t from, F filter) : from(from), filter(filter) {}
227  PoolIteratorFiltered<T, F> begin() { return PoolIteratorFiltered<T, F>(this->from, this->filter); }
228  PoolIteratorFiltered<T, F> end() { return PoolIteratorFiltered<T, F>(T::Pool::MAX_SIZE, this->filter); }
229  bool empty() { return this->begin() == this->end(); }
230  };
231 
236  template <struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero> *Tpool>
237  struct PoolItem {
238  Tindex index;
239 
241  typedef struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero> Pool;
242 
249  inline void *operator new(size_t size)
250  {
251  return Tpool->GetNew(size);
252  }
253 
259  inline void operator delete(void *p)
260  {
261  if (p == nullptr) return;
262  Titem *pn = static_cast<Titem *>(p);
263  assert(pn == Tpool->Get(pn->index));
264  Tpool->FreeItem(pn->index);
265  }
266 
275  inline void *operator new(size_t size, size_t index)
276  {
277  return Tpool->GetNew(size, index);
278  }
279 
287  inline void *operator new(size_t, void *ptr)
288  {
289  for (size_t i = 0; i < Tpool->first_unused; i++) {
290  /* Don't allow creating new objects over existing.
291  * Even if we called the destructor and reused this memory,
292  * we don't know whether 'size' and size of currently allocated
293  * memory are the same (because of possible inheritance).
294  * Use { size_t index = item->index; delete item; new (index) item; }
295  * instead to make sure destructor is called and no memory leaks. */
296  assert(ptr != Tpool->data[i]);
297  }
298  return ptr;
299  }
300 
301 
309  static inline bool CanAllocateItem(size_t n = 1)
310  {
311  return Tpool->CanAllocate(n);
312  }
313 
318  static inline bool CleaningPool()
319  {
320  return Tpool->cleaning;
321  }
322 
328  static inline bool IsValidID(size_t index)
329  {
330  return Tpool->IsValidID(index);
331  }
332 
339  static inline Titem *Get(size_t index)
340  {
341  return Tpool->Get(index);
342  }
343 
350  static inline Titem *GetIfValid(size_t index)
351  {
352  return index < Tpool->first_unused ? Tpool->Get(index) : nullptr;
353  }
354 
360  static inline size_t GetPoolSize()
361  {
362  return Tpool->first_unused;
363  }
364 
369  static inline size_t GetNumItems()
370  {
371  return Tpool->items;
372  }
373 
381  static inline void PostDestructor([[maybe_unused]] size_t index) { }
382 
388  static Pool::IterateWrapper<Titem> Iterate(size_t from = 0) { return Pool::IterateWrapper<Titem>(from); }
389  };
390 
391 private:
392  static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t);
393 
398  struct AllocCache {
401  };
402 
405 
406  void *AllocateItem(size_t size, size_t index);
407  void ResizeFor(size_t index);
408  size_t FindFirstFree();
409 
410  void *GetNew(size_t size);
411  void *GetNew(size_t size, size_t index);
412 
413  void FreeItem(size_t index);
414 };
415 
416 #endif /* POOL_TYPE_HPP */
DECLARE_ENUM_AS_BIT_SET(GenderEthnicity) enum CompanyManagerFaceVariable
Bitgroups of the CompanyManagerFace variable.
Type (helpers) for enums.
std::vector< struct PoolBase * > PoolVector
Vector of pointers to PoolBase.
Definition: pool_type.hpp:26
PoolType
Various types of a pool.
Definition: pool_type.hpp:16
@ PT_ALL
All pool types.
Definition: pool_type.hpp:22
@ PT_NONE
No pool is selected.
Definition: pool_type.hpp:17
@ PT_NADMIN
Network admin pool.
Definition: pool_type.hpp:20
@ PT_DATA
NewGRF or other data, that is not reset together with normal pools.
Definition: pool_type.hpp:21
@ PT_NORMAL
Normal pool containing game objects.
Definition: pool_type.hpp:18
@ PT_NCLIENT
Network client pools.
Definition: pool_type.hpp:19
#define MAX_UVALUE(type)
The largest value that can be entered in a variable.
Definition: stdafx.h:343
Base class for base of all pools.
Definition: pool_type.hpp:29
const PoolType type
Type of this pool.
Definition: pool_type.hpp:30
static PoolVector * GetPools()
Function used to access the vector of all pools.
Definition: pool_type.hpp:36
virtual void CleanPool()=0
Virtual method that deletes all items in the pool.
PoolBase(PoolType pt)
Constructor registers this object in the pool vector.
Definition: pool_type.hpp:48
PoolBase(const PoolBase &other)
Dummy private copy constructor to prevent compilers from copying the structure, which fails due to Ge...
Helper struct to cache 'freed' PoolItems so we do not need to allocate them again.
Definition: pool_type.hpp:398
AllocCache * next
The next in our 'cache'.
Definition: pool_type.hpp:400
Base class for all PoolItems.
Definition: pool_type.hpp:237
static size_t GetPoolSize()
Returns first unused index.
Definition: pool_type.hpp:360
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static void PostDestructor([[maybe_unused]] size_t index)
Dummy function called after destructor of each member.
Definition: pool_type.hpp:381
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:369
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
Definition: pool_type.hpp:318
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:309
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
Iterator to iterate all valid T of a pool.
Definition: pool_type.hpp:191
Iterator to iterate all valid T of a pool.
Definition: pool_type.hpp:147
Base class for all pools.
Definition: pool_type.hpp:80
void CleanPool() override
Virtual method that deletes all items in the pool.
Titem ** data
Pointer to array of pointers to Titem.
Definition: pool_type.hpp:100
size_t first_free
No item with index lower than this is free (doesn't say anything about this one!)
Definition: pool_type.hpp:92
const char *const name
Name of this pool.
Definition: pool_type.hpp:89
std::vector< BitmapStorage > used_bitmap
Bitmap of used indices.
Definition: pool_type.hpp:101
size_t first_unused
This and all higher indexes are free (doesn't say anything about first_unused-1 !)
Definition: pool_type.hpp:93
size_t size
Current allocated size.
Definition: pool_type.hpp:91
bool cleaning
True if cleaning pool (deleting all items)
Definition: pool_type.hpp:98
size_t items
Number of used indexes (non-nullptr)
Definition: pool_type.hpp:94
static constexpr size_t MAX_SIZE
Make template parameter accessible from outside.
Definition: pool_type.hpp:84
AllocCache * alloc_cache
Cache of freed pointers.
Definition: pool_type.hpp:404
bool CanAllocate(size_t n=1)
Tests whether we can allocate 'n' items.
Definition: pool_type.hpp:133
bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:123
static const size_t NO_FREE_ITEM
Constant to indicate we can't allocate any more items.
Definition: pool_type.hpp:392
Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:112