OpenTTD
pool_func.hpp
Go to the documentation of this file.
1 /* $Id$ */
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_FUNC_HPP
13 #define POOL_FUNC_HPP
14 
15 #include "alloc_func.hpp"
16 #include "mem_func.hpp"
17 #include "pool_type.hpp"
18 
23 #define DEFINE_POOL_METHOD(type) \
24  template <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size, PoolType Tpool_type, bool Tcache, bool Tzero> \
25  type Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tpool_type, Tcache, Tzero>
26 
31 DEFINE_POOL_METHOD(inline)::Pool(const char *name) :
32  PoolBase(Tpool_type),
33  name(name),
34  size(0),
35  first_free(0),
36  first_unused(0),
37  items(0),
38 #ifdef OTTD_ASSERT
39  checked(0),
40 #endif /* OTTD_ASSERT */
41  cleaning(false),
42  data(NULL),
43  alloc_cache(NULL)
44 { }
45 
52 DEFINE_POOL_METHOD(inline void)::ResizeFor(size_t index)
53 {
54  assert(index >= this->size);
55  assert(index < Tmax_size);
56 
57  size_t new_size = min(Tmax_size, Align(index + 1, Tgrowth_step));
58 
59  this->data = ReallocT(this->data, new_size);
60  MemSetT(this->data + this->size, 0, new_size - this->size);
61 
62  this->size = new_size;
63 }
64 
69 DEFINE_POOL_METHOD(inline size_t)::FindFirstFree()
70 {
71  size_t index = this->first_free;
72 
73  for (; index < this->first_unused; index++) {
74  if (this->data[index] == NULL) return index;
75  }
76 
77  if (index < this->size) {
78  return index;
79  }
80 
81  assert(index == this->size);
82  assert(this->first_unused == this->size);
83 
84  if (index < Tmax_size) {
85  this->ResizeFor(index);
86  return index;
87  }
88 
89  assert(this->items == Tmax_size);
90 
91  return NO_FREE_ITEM;
92 }
93 
101 DEFINE_POOL_METHOD(inline void *)::AllocateItem(size_t size, size_t index)
102 {
103  assert(this->data[index] == NULL);
104 
105  this->first_unused = max(this->first_unused, index + 1);
106  this->items++;
107 
108  Titem *item;
109  if (Tcache && this->alloc_cache != NULL) {
110  assert(sizeof(Titem) == size);
111  item = (Titem *)this->alloc_cache;
112  this->alloc_cache = this->alloc_cache->next;
113  if (Tzero) {
114  /* Explicitly casting to (void *) prevents a clang warning -
115  * we are actually memsetting a (not-yet-constructed) object */
116  memset((void *)item, 0, sizeof(Titem));
117  }
118  } else if (Tzero) {
119  item = (Titem *)CallocT<byte>(size);
120  } else {
121  item = (Titem *)MallocT<byte>(size);
122  }
123  this->data[index] = item;
124  item->index = (Tindex)(uint)index;
125  return item;
126 }
127 
134 DEFINE_POOL_METHOD(void *)::GetNew(size_t size)
135 {
136  size_t index = this->FindFirstFree();
137 
138 #ifdef OTTD_ASSERT
139  assert(this->checked != 0);
140  this->checked--;
141 #endif /* OTTD_ASSERT */
142  if (index == NO_FREE_ITEM) {
143  error("%s: no more free items", this->name);
144  }
145 
146  this->first_free = index + 1;
147  return this->AllocateItem(size, index);
148 }
149 
157 DEFINE_POOL_METHOD(void *)::GetNew(size_t size, size_t index)
158 {
159  extern void NORETURN SlErrorCorruptFmt(const char *format, ...);
160 
161  if (index >= Tmax_size) {
162  SlErrorCorruptFmt("%s index " PRINTF_SIZE " out of range (" PRINTF_SIZE ")", this->name, index, Tmax_size);
163  }
164 
165  if (index >= this->size) this->ResizeFor(index);
166 
167  if (this->data[index] != NULL) {
168  SlErrorCorruptFmt("%s index " PRINTF_SIZE " already in use", this->name, index);
169  }
170 
171  return this->AllocateItem(size, index);
172 }
173 
180 DEFINE_POOL_METHOD(void)::FreeItem(size_t index)
181 {
182  assert(index < this->size);
183  assert(this->data[index] != NULL);
184  if (Tcache) {
185  AllocCache *ac = (AllocCache *)this->data[index];
186  ac->next = this->alloc_cache;
187  this->alloc_cache = ac;
188  } else {
189  free(this->data[index]);
190  }
191  this->data[index] = NULL;
192  this->first_free = min(this->first_free, index);
193  this->items--;
194  if (!this->cleaning) Titem::PostDestructor(index);
195 }
196 
198 DEFINE_POOL_METHOD(void)::CleanPool()
199 {
200  this->cleaning = true;
201  for (size_t i = 0; i < this->first_unused; i++) {
202  delete this->Get(i); // 'delete NULL;' is very valid
203  }
204  assert(this->items == 0);
205  free(this->data);
206  this->first_unused = this->first_free = this->size = 0;
207  this->data = NULL;
208  this->cleaning = false;
209 
210  if (Tcache) {
211  while (this->alloc_cache != NULL) {
212  AllocCache *ac = this->alloc_cache;
213  this->alloc_cache = ac->next;
214  free(ac);
215  }
216  }
217 }
218 
219 #undef DEFINE_POOL_METHOD
220 
226 #define INSTANTIATE_POOL_METHODS(name) \
227  template void * name ## Pool::GetNew(size_t size); \
228  template void * name ## Pool::GetNew(size_t size, size_t index); \
229  template void name ## Pool::FreeItem(size_t index); \
230  template void name ## Pool::CleanPool();
231 
232 #endif /* POOL_FUNC_HPP */
Base class for base of all pools.
Definition: pool_type.hpp:32
void NORETURN SlErrorCorruptFmt(const char *format,...)
Issue an SlErrorCorrupt with a format string.
Definition: saveload.cpp:360
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
Defintion of Pool, structure used to access PoolItems, and PoolItem, base structure for Vehicle...
static T Align(const T x, uint n)
Return the smallest multiple of n equal or greater than x.
Definition: math_func.hpp:97
Functions related to the allocation of memory.
static T * ReallocT(T *t_ptr, size_t num_elements)
Simplified reallocation function that allocates the specified number of elements of the given type...
Definition: alloc_func.hpp:113
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
Base class for all pools.
Definition: pool_type.hpp:83
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:112
#define DEFINE_POOL_METHOD(type)
Helper for defining the method&#39;s signature.
Definition: pool_func.hpp:23
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:114
Functions related to memory operations.
static void MemSetT(T *ptr, byte value, size_t num=1)
Type-safe version of memset().
Definition: mem_func.hpp:51