OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

pool_type.hpp
Go to the documentation of this file.
1 /* $Id: pool_type.hpp 26333 2014-02-11 20:34:48Z frosch $ */
2
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
9
12 #ifndef POOL_TYPE_HPP
13 #define POOL_TYPE_HPP
14
15 #include "smallvec_type.hpp"
16 #include "enum_type.hpp"
17
19 enum PoolType {
20 PT_NONE = 0x00,
21 PT_NORMAL = 0x01,
22 PT_NCLIENT = 0x02,
23 PT_NADMIN = 0x04,
24 PT_DATA = 0x08,
25 PT_ALL = 0x0F,
26 };
27 DECLARE_ENUM_AS_BIT_SET(PoolType)
28
29 typedef SmallVector<struct PoolBase *, 4> PoolVector;
30
32 struct PoolBase {
33 const PoolType type;
34
39 static PoolVector *GetPools()
40 {
41 static PoolVector *pools = new PoolVector();
42 return pools;
43 }
44
45 static void Clean(PoolType);
46
51 PoolBase(PoolType pt) : type(pt)
52 {
53 *PoolBase::GetPools()->Append() = this;
54 }
55
56 virtual ~PoolBase();
57
61 virtual void CleanPool() = 0;
62
63 private:
68 PoolBase(const PoolBase &other);
69 };
70
82 template <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size, PoolType Tpool_type = PT_NORMAL, bool Tcache = false, bool Tzero = true>
83 struct Pool : PoolBase {
84 /* Ensure Tmax_size is within the bounds of Tindex. */
85 assert_compile((uint64)(Tmax_size - 1) >> 8 * sizeof(Tindex) == 0);
86
87 static const size_t MAX_SIZE = Tmax_size;
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 OTTD_ASSERT
96 size_t checked;
97 #endif /* OTTD_ASSERT */
98 bool cleaning;
99
100 Titem **data;
101
102 Pool(const char *name);
103 virtual void CleanPool();
104
111 inline Titem *Get(size_t index)
112 {
113 assert(index < this->first_unused);
114 return this->data[index];
115 }
116
122 inline bool IsValidID(size_t index)
123 {
124 return index < this->first_unused && this->Get(index) != NULL;
125 }
126
132 inline bool CanAllocate(size_t n = 1)
133 {
134 bool ret = this->items <= Tmax_size - n;
135 #ifdef OTTD_ASSERT
136 this->checked = ret ? n : 0;
137 #endif /* OTTD_ASSERT */
138 return ret;
139 }
140
145 template <struct Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero> *Tpool>
146 struct PoolItem {
147 Tindex index;
148
155 inline void *operator new(size_t size)
156 {
157 return Tpool->GetNew(size);
158 }
159
165 inline void operator delete(void *p)
166 {
167 if (p == NULL) return;
168 Titem *pn = (Titem *)p;
169 assert(pn == Tpool->Get(pn->index));
170 Tpool->FreeItem(pn->index);
171 }
172
181 inline void *operator new(size_t size, size_t index)
182 {
183 return Tpool->GetNew(size, index);
184 }
185
194 inline void *operator new(size_t size, void *ptr)
195 {
196 for (size_t i = 0; i < Tpool->first_unused; i++) {
197 /* Don't allow creating new objects over existing.
198 * Even if we called the destructor and reused this memory,
199 * we don't know whether 'size' and size of currently allocated
200 * memory are the same (because of possible inheritance).
201 * Use { size_t index = item->index; delete item; new (index) item; }
202 * instead to make sure destructor is called and no memory leaks. */
203 assert(ptr != Tpool->data[i]);
204 }
205 return ptr;
206 }
207
208
216 static inline bool CanAllocateItem(size_t n = 1)
217 {
218 return Tpool->CanAllocate(n);
219 }
220
225 static inline bool CleaningPool()
226 {
227 return Tpool->cleaning;
228 }
229
235 static inline bool IsValidID(size_t index)
236 {
237 return Tpool->IsValidID(index);
238 }
239
246 static inline Titem *Get(size_t index)
247 {
248 return Tpool->Get(index);
249 }
250
257 static inline Titem *GetIfValid(size_t index)
258 {
259 return index < Tpool->first_unused ? Tpool->Get(index) : NULL;
260 }
261
267 static inline size_t GetPoolSize()
268 {
269 return Tpool->first_unused;
270 }
271
276 static inline size_t GetNumItems()
277 {
278 return Tpool->items;
279 }
280
288 static inline void PostDestructor(size_t index) { }
289 };
290
291 private:
292 static const size_t NO_FREE_ITEM = MAX_UVALUE(size_t);
293
298 struct AllocCache {
300 AllocCache *next;
301 };
302
304 AllocCache *alloc_cache;
305
306 void *AllocateItem(size_t size, size_t index);
307 void ResizeFor(size_t index);
308 size_t FindFirstFree();
309
310 void *GetNew(size_t size);
311 void *GetNew(size_t size, size_t index);
312
313 void FreeItem(size_t index);
314 };
315
316 #define FOR_ALL_ITEMS_FROM(type, iter, var, start) \
317 for (size_t iter = start; var = NULL, iter < type::GetPoolSize(); iter++) \
318 if ((var = type::Get(iter)) != NULL)
319
320 #define FOR_ALL_ITEMS(type, iter, var) FOR_ALL_ITEMS_FROM(type, iter, var, 0)
321
322 #endif /* POOL_TYPE_HPP */