OpenTTD Source: src/core/pool_type.hpp Source File

OpenTTD Source 15.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};
24 DECLARE_ENUM_AS_BIT_SET(PoolType)
25
26typedef std::vector<struct PoolBase *> PoolVector;
27
29struct 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
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>
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>
191 struct PoolIteratorFiltered {
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>
223 struct IterateWrapperFiltered {
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 {
400 AllocCache *next;
401 };
402
404 AllocCache *alloc_cache;
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 */
enum_type.hpp
Type (helpers) for enums.
DECLARE_ENUM_AS_BIT_SET
#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
PoolVector
std::vector< struct PoolBase * > PoolVector
Vector of pointers to PoolBase.
Definition pool_type.hpp:26
PoolType
PoolType
Various types of a pool.
Definition pool_type.hpp:16
PT_ALL
@ PT_ALL
All pool types.
Definition pool_type.hpp:22
PT_NONE
@ PT_NONE
No pool is selected.
Definition pool_type.hpp:17
PT_NADMIN
@ PT_NADMIN
Network admin pool.
Definition pool_type.hpp:20
PT_DATA
@ PT_DATA
NewGRF or other data, that is not reset together with normal pools.
Definition pool_type.hpp:21
PT_NORMAL
@ PT_NORMAL
Normal pool containing game objects.
Definition pool_type.hpp:18
PT_NCLIENT
@ PT_NCLIENT
Network client pools.
Definition pool_type.hpp:19
MAX_UVALUE
#define MAX_UVALUE(type)
The largest value that can be entered in a variable.
Definition stdafx.h:343
PoolBase
Base class for base of all pools.
Definition pool_type.hpp:29
PoolBase::type
const PoolType type
Type of this pool.
Definition pool_type.hpp:30
PoolBase::CleanPool
virtual void CleanPool()=0
Virtual method that deletes all items in the pool.
PoolBase::GetPools
static PoolVector * GetPools()
Function used to access the vector of all pools.
Definition pool_type.hpp:36
PoolBase::PoolBase
PoolBase(PoolType pt)
Constructor registers this object in the pool vector.
Definition pool_type.hpp:48
PoolBase::PoolBase
PoolBase(const PoolBase &other)
Dummy private copy constructor to prevent compilers from copying the structure, which fails due to Ge...
Pool::AllocCache
Helper struct to cache 'freed' PoolItems so we do not need to allocate them again.
Definition pool_type.hpp:398
Pool::AllocCache::next
AllocCache * next
The next in our 'cache'.
Definition pool_type.hpp:400
Pool::IterateWrapperFiltered
Definition pool_type.hpp:223
Pool::IterateWrapper
Definition pool_type.hpp:178
Pool::PoolItem
Base class for all PoolItems.
Definition pool_type.hpp:237
Pool::PoolItem::GetPoolSize
static size_t GetPoolSize()
Returns first unused index.
Definition pool_type.hpp:360
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition pool_type.hpp:238
Pool::PoolItem::PostDestructor
static void PostDestructor(size_t index)
Dummy function called after destructor of each member.
Definition pool_type.hpp:381
Pool::PoolItem::GetNumItems
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition pool_type.hpp:369
Pool::PoolItem::CleaningPool
static bool CleaningPool()
Returns current state of pool cleaning - yes or no.
Definition pool_type.hpp:318
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:328
Pool::PoolItem::Iterate
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition pool_type.hpp:388
Pool::PoolItem::GetIfValid
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition pool_type.hpp:350
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:309
Pool::PoolItem::Get
static Titem * Get(size_t index)
Returns Titem with given index.
Definition pool_type.hpp:339
Pool::PoolIteratorFiltered
Iterator to iterate all valid T of a pool.
Definition pool_type.hpp:191
Pool::PoolIterator
Iterator to iterate all valid T of a pool.
Definition pool_type.hpp:147
Pool
Base class for all pools.
Definition pool_type.hpp:80
Pool::CleanPool
void CleanPool() override
Virtual method that deletes all items in the pool.
Pool::data
Titem ** data
Pointer to array of pointers to Titem.
Definition pool_type.hpp:100
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:92
Pool::name
const char *const name
Name of this pool.
Definition pool_type.hpp:89
Pool::used_bitmap
std::vector< BitmapStorage > used_bitmap
Bitmap of used indices.
Definition pool_type.hpp:101
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:93
Pool::size
size_t size
Current allocated size.
Definition pool_type.hpp:91
Pool::cleaning
bool cleaning
True if cleaning pool (deleting all items)
Definition pool_type.hpp:98
Pool::items
size_t items
Number of used indexes (non-nullptr)
Definition pool_type.hpp:94
Pool::Get
Titem * Get(size_t index)
Returns Titem with given index.
Definition pool_type.hpp:112
Pool::MAX_SIZE
static constexpr size_t MAX_SIZE
Make template parameter accessible from outside.
Definition pool_type.hpp:84
Pool::alloc_cache
AllocCache * alloc_cache
Cache of freed pointers.
Definition pool_type.hpp:404
Pool::CanAllocate
bool CanAllocate(size_t n=1)
Tests whether we can allocate 'n' items.
Definition pool_type.hpp:133
Pool::IsValidID
bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition pool_type.hpp:123
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:392