OpenTTD Source 20241224-master-gf74b0cf984
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
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
26typedef std::vector<struct PoolBase *> PoolVector;
27
29struct PoolBase {
30 const PoolType type;
31
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
60private:
65 PoolBase(const PoolBase &other);
66};
67
79template <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size, PoolType Tpool_type = PT_NORMAL, bool Tcache = false, bool Tzero = true>
80struct 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>
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>
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
391private:
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 */
Type (helpers) for enums.
#define DECLARE_ENUM_AS_BIT_SET(enum_type)
Operators to allow to work with enum as with type safe bit set in C++.
Definition enum_type.hpp:35
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
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:36
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.
AllocCache * next
The next in our 'cache'.
Base class for all PoolItems.
static size_t GetPoolSize()
Returns first unused index.
Tindex index
Index of this pool item.
static void PostDestructor(size_t index)
Dummy function called after destructor of each member.
static size_t GetNumItems()
Returns number of valid items in the pool.
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static Titem * Get(size_t index)
Returns Titem with given index.
Iterator to iterate all valid T of a pool.
Iterator to iterate all valid T of a pool.
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.
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.
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
Titem * Get(size_t index)
Returns Titem with given index.
static constexpr size_t MAX_SIZE
Make template parameter accessible from outside.
Definition pool_type.hpp:84
AllocCache * alloc_cache
Cache of freed pointers.
bool CanAllocate(size_t n=1)
Tests whether we can allocate 'n' items.
bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static const size_t NO_FREE_ITEM
Constant to indicate we can't allocate any more items.