OpenTTD Source 20260621-master-g720d10536d
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#ifndef POOL_TYPE_HPP
11#define POOL_TYPE_HPP
12
13#include "enum_type.hpp"
14
22
25
27
28typedef std::vector<struct PoolBase *> PoolVector;
29
30template <typename Tindex>
31using AllocationResult = std::pair<void *, Tindex>;
32
33
35struct PoolIDBase {};
36
49template <typename TBaseType, typename TTag, TBaseType TEnd, TBaseType TInvalid>
50struct EMPTY_BASES PoolID : PoolIDBase {
51 using BaseType = TBaseType;
52
53 constexpr PoolID() = default;
54 constexpr PoolID(const PoolID &) = default;
55 constexpr PoolID(PoolID &&) = default;
56
57 explicit constexpr PoolID(const TBaseType &value) : value(value) {}
58
59 constexpr PoolID &operator =(const PoolID &rhs) { this->value = rhs.value; return *this; }
60 constexpr PoolID &operator =(PoolID &&rhs) { this->value = std::move(rhs.value); return *this; }
61
62 /* Only allow conversion to BaseType via method. */
63 constexpr TBaseType base() const noexcept { return this->value; }
64
65 static constexpr PoolID Begin() { return PoolID{}; }
66 static constexpr PoolID End() { return PoolID{static_cast<TBaseType>(TEnd)}; }
67 static constexpr PoolID Invalid() { return PoolID{static_cast<TBaseType>(TInvalid)}; }
68
69 constexpr auto operator++() { ++this->value; return this; }
70 constexpr auto operator+(const std::integral auto &val) const { return this->value + val; }
71 constexpr auto operator-(const std::integral auto &val) const { return this->value - val; }
72 constexpr auto operator%(const std::integral auto &val) const { return this->value % val; }
73
74 constexpr bool operator==(const PoolID<TBaseType, TTag, TEnd, TInvalid> &rhs) const { return this->value == rhs.value; }
75 constexpr auto operator<=>(const PoolID<TBaseType, TTag, TEnd, TInvalid> &rhs) const { return this->value <=> rhs.value; }
76
77 constexpr bool operator==(const size_t &rhs) const { return this->value == rhs; }
78 constexpr auto operator<=>(const size_t &rhs) const { return this->value <=> rhs; }
79private:
81 TBaseType value;
82};
83
84template <typename T> requires std::is_base_of_v<PoolIDBase, T>
85constexpr auto operator+(const std::integral auto &val, const T &pool_id) { return pool_id + val; }
86template <typename Te, typename Tp> requires std::is_enum_v<Te> && std::is_base_of_v<PoolIDBase, Tp>
87constexpr auto operator+(const Te &val, const Tp &pool_id) { return pool_id + to_underlying(val); }
88
90struct PoolBase {
91 const PoolType type;
92
98 {
99 static PoolVector *pools = new PoolVector();
100 return pools;
101 }
102
103 static void Clean(PoolTypes);
104
110 {
111 PoolBase::GetPools()->push_back(this);
112 }
113
115 virtual ~PoolBase();
116
120 virtual void CleanPool() = 0;
121
122private:
128 PoolBase(const PoolBase &other);
129};
130
140template <class Titem, typename Tindex, size_t Tgrowth_step, PoolType Tpool_type = PoolType::Normal, bool Tcache = false>
141requires std::is_base_of_v<PoolIDBase, Tindex>
142struct Pool : PoolBase {
143public:
144 static constexpr size_t MAX_SIZE = Tindex::End().base();
145
146 using IndexType = Tindex;
147 using BitmapStorage = size_t;
148 static constexpr size_t BITMAP_SIZE = std::numeric_limits<BitmapStorage>::digits;
149
150 const std::string_view name{};
151
152 size_t first_free = 0;
153 size_t first_unused = 0;
154 size_t items = 0;
155#ifdef WITH_ASSERT
156 size_t checked = 0;
157#endif /* WITH_ASSERT */
158 bool cleaning = false;
159
160 std::vector<Titem *> data{};
161 std::vector<BitmapStorage> used_bitmap{};
162
163 Pool(std::string_view name) : PoolBase(Tpool_type), name(name) {}
164 void CleanPool() override;
165
172 inline Titem *Get(size_t index)
173 {
174 assert(index < this->first_unused);
175 return this->data[index];
176 }
177
183 inline bool IsValidID(size_t index)
184 {
185 return index < this->first_unused && this->Get(index) != nullptr;
186 }
187
193 inline bool CanAllocate(size_t n = 1)
194 {
195 bool ret = this->items <= MAX_SIZE - n;
196#ifdef WITH_ASSERT
197 this->checked = ret ? n : 0;
198#endif /* WITH_ASSERT */
199 return ret;
200 }
201
206 template <class T>
207 struct PoolIterator {
208 typedef T value_type;
209 typedef T *pointer;
210 typedef T &reference;
211 typedef size_t difference_type;
212 typedef std::forward_iterator_tag iterator_category;
213
214 explicit PoolIterator(size_t index) : index(index)
215 {
216 this->ValidateIndex();
217 };
218
219 bool operator==(const PoolIterator &other) const { return this->index == other.index; }
220 T * operator*() const { return T::Get(this->index); }
221 PoolIterator & operator++() { this->index++; this->ValidateIndex(); return *this; }
222
223 private:
224 size_t index;
225 void ValidateIndex()
226 {
227 while (this->index < T::GetPoolSize() && !(T::IsValidID(this->index))) this->index++;
228 if (this->index >= T::GetPoolSize()) this->index = T::Pool::MAX_SIZE;
229 }
230 };
231
232 /*
233 * Iterable ensemble of all valid T
234 * @tparam T Type of the class/struct that is going to be iterated
235 */
236 template <class T>
237 struct IterateWrapper {
238 size_t from;
239 IterateWrapper(size_t from = 0) : from(from) {}
240 PoolIterator<T> begin() { return PoolIterator<T>(this->from); }
241 PoolIterator<T> end() { return PoolIterator<T>(T::Pool::MAX_SIZE); }
242 bool empty() { return this->begin() == this->end(); }
243 };
244
249 template <class T, class F>
250 struct PoolIteratorFiltered {
251 typedef T value_type;
252 typedef T *pointer;
253 typedef T &reference;
254 typedef size_t difference_type;
255 typedef std::forward_iterator_tag iterator_category;
256
257 explicit PoolIteratorFiltered(size_t index, F filter) : index(index), filter(filter)
258 {
259 this->ValidateIndex();
260 };
261
262 bool operator==(const PoolIteratorFiltered &other) const { return this->index == other.index; }
263 T * operator*() const { return T::Get(this->index); }
264 PoolIteratorFiltered & operator++() { this->index++; this->ValidateIndex(); return *this; }
265
266 private:
267 size_t index;
268 F filter;
269 void ValidateIndex()
270 {
271 while (this->index < T::GetPoolSize() && !(T::IsValidID(this->index) && this->filter(this->index))) this->index++;
272 if (this->index >= T::GetPoolSize()) this->index = T::Pool::MAX_SIZE;
273 }
274 };
275
276 /*
277 * Iterable ensemble of all valid T
278 * @tparam T Type of the class/struct that is going to be iterated
279 */
280 template <class T, class F>
281 struct IterateWrapperFiltered {
282 size_t from;
283 F filter;
284 IterateWrapperFiltered(size_t from, F filter) : from(from), filter(filter) {}
285 PoolIteratorFiltered<T, F> begin() { return PoolIteratorFiltered<T, F>(this->from, this->filter); }
286 PoolIteratorFiltered<T, F> end() { return PoolIteratorFiltered<T, F>(T::Pool::MAX_SIZE, this->filter); }
287 bool empty() { return this->begin() == this->end(); }
288 };
289
294 template <struct Pool<Titem, Tindex, Tgrowth_step, Tpool_type, Tcache> *Tpool>
295 struct PoolItem {
296 const Tindex index;
297
302 PoolItem(Tindex index) : index(index) {}
303
305 typedef struct Pool<Titem, Tindex, Tgrowth_step, Tpool_type, Tcache> Pool;
306
308 inline void *operator new(size_t) = delete;
309
316 inline void operator delete(void *p, size_t size)
317 {
318 if (p == nullptr) return;
319 Titem *pn = static_cast<Titem *>(p);
320 assert(pn == Tpool->Get(Pool::GetRawIndex(pn->index)));
321 Tpool->FreeItem(size, Pool::GetRawIndex(pn->index));
322 }
323
325 inline void *operator new(size_t size, Tindex index) = delete;
326
328 inline void *operator new(size_t, void *ptr) = delete;
329
330
336 template <typename T = Titem, typename... Targs>
337 requires std::is_base_of_v<Titem, T>
338 static inline T *Create(Targs &&... args)
339 {
340 auto [data, index] = Tpool->GetNew(sizeof(T));
341 return ::new (data) T(index, std::forward<Targs&&>(args)...);
342 }
343
350 template <typename T = Titem, typename... Targs>
351 requires std::is_base_of_v<Titem, T>
352 static inline T *CreateAtIndex(Tindex index, Targs &&... args)
353 {
354 auto [data, _] = Tpool->GetNew(sizeof(T), index.base());
355 return ::new (data) T(index, std::forward<Targs&&>(args)...);
356 }
357
359
365 static inline bool CanAllocateItem(size_t n = 1)
366 {
367 return Tpool->CanAllocate(n);
368 }
369
374 static inline bool CleaningPool()
375 {
376 return Tpool->cleaning;
377 }
378
384 static inline bool IsValidID(auto index)
385 {
386 return Tpool->IsValidID(GetRawIndex(index));
387 }
388
395 static inline Titem *Get(auto index)
396 {
397 return Tpool->Get(GetRawIndex(index));
398 }
399
406 static inline Titem *GetIfValid(auto index)
407 {
408 return GetRawIndex(index) < Tpool->first_unused ? Tpool->Get(GetRawIndex(index)) : nullptr;
409 }
410
416 static inline size_t GetPoolSize()
417 {
418 return Tpool->first_unused;
419 }
420
425 static inline size_t GetNumItems()
426 {
427 return Tpool->items;
428 }
429
437 static inline void PostDestructor([[maybe_unused]] size_t index) { }
438
444 static Pool::IterateWrapper<Titem> Iterate(size_t from = 0) { return Pool::IterateWrapper<Titem>(from); }
445 };
446
447private:
448 static const size_t NO_FREE_ITEM = std::numeric_limits<size_t>::max();
449
454 struct AllocCache {
457 };
458
460 AllocCache *alloc_cache = nullptr;
461 std::allocator<uint8_t> allocator{};
462
463 AllocationResult<Tindex> AllocateItem(size_t size, size_t index);
464 void ResizeFor(size_t index);
466
467 AllocationResult<Tindex> GetNew(size_t size);
468 AllocationResult<Tindex> GetNew(size_t size, size_t index);
469
470 void FreeItem(size_t size, size_t index);
471
472 static constexpr size_t GetRawIndex(size_t index) { return index; }
473 template <typename T> requires std::is_base_of_v<PoolIDBase, T>
474 static constexpr size_t GetRawIndex(const T &index) { return index.base(); }
475};
476
477#endif /* POOL_TYPE_HPP */
@ End
We are looking for this amount of GRFs.
@ Invalid
Invalid town production effect.
Definition cargotype.h:46
@ Begin
Used for iteration.
Definition cargotype.h:23
Enum-as-bit-set wrapper.
#define T
Climate temperate.
Definition engines.h:91
Type (helpers) for enums.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
constexpr enum_type & operator++(enum_type &e)
Prefix increment.
Definition enum_type.hpp:41
constexpr enum_type operator-(enum_type e, int offset)
Subtract integer.
constexpr enum_type operator+(enum_type e, int offset)
Add integer.
PoolType
Various types of a pool.
Definition pool_type.hpp:16
@ NetworkClient
Network client pools.
Definition pool_type.hpp:18
@ NetworkAdmin
Network admin pool.
Definition pool_type.hpp:19
@ Normal
Normal pool containing game objects.
Definition pool_type.hpp:17
@ Data
NewGRF or other data, that is not reset together with normal pools.
Definition pool_type.hpp:20
std::vector< struct PoolBase * > PoolVector
Vector of pointers to PoolBase.
Definition pool_type.hpp:28
EnumBitSet< PoolType, uint8_t > PoolTypes
Bitset of PoolType elements.
Definition pool_type.hpp:24
Base class for base of all pools.
Definition pool_type.hpp:90
const PoolType type
Type of this pool.
Definition pool_type.hpp:91
virtual void CleanPool()=0
Virtual method that deletes all items in the pool.
static PoolVector * GetPools()
Function used to access the vector of all pools.
Definition pool_type.hpp:97
PoolBase(PoolType pt)
Constructor registers this object in the pool vector.
static void Clean(PoolTypes)
Clean all pools of given type.
Definition pool_func.cpp:30
virtual ~PoolBase()
Ensure the destructor of the sub classes are called as well.
Definition pool_func.cpp:19
PoolBase(const PoolBase &other)
Dummy private copy constructor to prevent compilers from copying the structure, which fails due to Ge...
Non-templated base for PoolID for use with type trait queries.
Definition pool_type.hpp:35
TBaseType value
The bare storage.
Definition pool_type.hpp:81
Helper struct to cache 'freed' PoolItems so we do not need to allocate them again.
AllocCache * next
The next in our 'cache'.
PoolItem(Tindex index)
Construct the item.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static T * CreateAtIndex(Tindex index, Targs &&... args)
Creates a new T-object in the associated pool.
static size_t GetPoolSize()
Returns first unused index.
struct Pool< Titem, Tindex, Tgrowth_step, Tpool_type, Tcache > Pool
Type of the pool this item is going to be part of.
static Titem * Get(auto index)
Returns Titem with given index.
static size_t GetNumItems()
Returns number of valid items in the pool.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function().
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static T * Create(Targs &&... args)
Creates a new T-object in the associated pool.
const Tindex index
Index of this pool item.
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
static void PostDestructor(size_t index)
Dummy function called after destructor of each member.
Iterator to iterate all valid T of a pool.
Iterator to iterate all valid T of a pool.
Base class for all pools.
bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
size_t FindFirstFree()
Searches for first free index.
Definition pool_func.hpp:59
void CleanPool() override
Destroys all items in the pool and resets all member variables.
std::vector< EngineRenew * > data
AllocationResult< Tindex > AllocateItem(size_t size, size_t index)
Makes given index valid.
Definition pool_func.hpp:87
std::vector< BitmapStorage > used_bitmap
void ResizeFor(size_t index)
Resizes the pool so 'index' can be addressed.
Definition pool_func.hpp:35
Titem * Get(size_t index)
Returns Titem with given index.
AllocationResult< Tindex > GetNew(size_t size)
Allocates new item.
void FreeItem(size_t size, size_t index)
Deallocates memory used by this index and marks item as free.
AllocationResult< Tindex > GetNew(size_t size, size_t index)
Allocates new item with given index.
bool CanAllocate(size_t n=1)
Tests whether we can allocate 'n' items.