Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef POOL_FUNC_HPP
00013 #define POOL_FUNC_HPP
00014
00015 #include "alloc_func.hpp"
00016 #include "mem_func.hpp"
00017 #include "pool_type.hpp"
00018
00019 #define DEFINE_POOL_METHOD(type) \
00020 template <class Titem, typename Tindex, size_t Tgrowth_step, size_t Tmax_size, bool Tcache, bool Tzero> \
00021 type Pool<Titem, Tindex, Tgrowth_step, Tmax_size, Tcache, Tzero>
00022
00027 DEFINE_POOL_METHOD(inline)::Pool(const char *name) :
00028 name(name),
00029 size(0),
00030 first_free(0),
00031 first_unused(0),
00032 items(0),
00033 cleaning(false),
00034 data(NULL),
00035 alloc_cache(NULL)
00036 { }
00037
00044 DEFINE_POOL_METHOD(inline void)::ResizeFor(size_t index)
00045 {
00046 assert(index >= this->size);
00047 assert(index < Tmax_size);
00048
00049 size_t new_size = min(Tmax_size, Align(index + 1, Tgrowth_step));
00050
00051 this->data = ReallocT(this->data, new_size);
00052 MemSetT(this->data + this->size, 0, new_size - this->size);
00053
00054 this->size = new_size;
00055 }
00056
00061 DEFINE_POOL_METHOD(inline size_t)::FindFirstFree()
00062 {
00063 size_t index = this->first_free;
00064
00065 for (; index < this->first_unused; index++) {
00066 if (this->data[index] == NULL) return index;
00067 }
00068
00069 if (index < this->size) {
00070 return index;
00071 }
00072
00073 assert(index == this->size);
00074 assert(this->first_unused == this->size);
00075
00076 if (index < Tmax_size) {
00077 this->ResizeFor(index);
00078 return index;
00079 }
00080
00081 assert(this->items == Tmax_size);
00082
00083 return NO_FREE_ITEM;
00084 }
00085
00093 DEFINE_POOL_METHOD(inline void *)::AllocateItem(size_t size, size_t index)
00094 {
00095 assert(this->data[index] == NULL);
00096
00097 this->first_unused = max(this->first_unused, index + 1);
00098 this->items++;
00099
00100 Titem *item;
00101 if (Tcache && this->alloc_cache != NULL) {
00102 assert(sizeof(Titem) == size);
00103 item = (Titem *)this->alloc_cache;
00104 this->alloc_cache = this->alloc_cache->next;
00105 if (Tzero) MemSetT(item, 0);
00106 } else if (Tzero) {
00107 item = (Titem *)CallocT<byte>(size);
00108 } else {
00109 item = (Titem *)MallocT<byte>(size);
00110 }
00111 this->data[index] = item;
00112 item->index = (uint)index;
00113 return item;
00114 }
00115
00122 DEFINE_POOL_METHOD(void *)::GetNew(size_t size)
00123 {
00124 size_t index = this->FindFirstFree();
00125
00126 if (index == NO_FREE_ITEM) {
00127 error("%s: no more free items", this->name);
00128 }
00129
00130 this->first_free = index + 1;
00131 return this->AllocateItem(size, index);
00132 }
00133
00141 DEFINE_POOL_METHOD(void *)::GetNew(size_t size, size_t index)
00142 {
00143 if (index >= Tmax_size) {
00144 usererror("failed loading savegame: %s index " PRINTF_SIZE " out of range (" PRINTF_SIZE ")", this->name, index, Tmax_size);
00145 }
00146
00147 if (index >= this->size) this->ResizeFor(index);
00148
00149 if (this->data[index] != NULL) {
00150 usererror("failed loading savegame: %s index " PRINTF_SIZE " already in use", this->name, index);
00151 }
00152
00153 return this->AllocateItem(size, index);
00154 }
00155
00162 DEFINE_POOL_METHOD(void)::FreeItem(size_t index)
00163 {
00164 assert(index < this->size);
00165 assert(this->data[index] != NULL);
00166 if (Tcache) {
00167 AllocCache *ac = (AllocCache *)this->data[index];
00168 ac->next = this->alloc_cache;
00169 this->alloc_cache = ac;
00170 } else {
00171 free(this->data[index]);
00172 }
00173 this->data[index] = NULL;
00174 this->first_free = min(this->first_free, index);
00175 this->items--;
00176 if (!this->cleaning) Titem::PostDestructor(index);
00177 }
00178
00180 DEFINE_POOL_METHOD(void)::CleanPool()
00181 {
00182 this->cleaning = true;
00183 for (size_t i = 0; i < this->first_unused; i++) {
00184 delete this->Get(i);
00185 }
00186 assert(this->items == 0);
00187 free(this->data);
00188 this->first_unused = this->first_free = this->size = 0;
00189 this->data = NULL;
00190 this->cleaning = false;
00191
00192 if (Tcache) {
00193 while (this->alloc_cache != NULL) {
00194 AllocCache *ac = this->alloc_cache;
00195 this->alloc_cache = ac->next;
00196 free(ac);
00197 }
00198 }
00199 }
00200
00201 #undef DEFINE_POOL_METHOD
00202
00208 #define INSTANTIATE_POOL_METHODS(name) \
00209 template void * name ## Pool::GetNew(size_t size); \
00210 template void * name ## Pool::GetNew(size_t size, size_t index); \
00211 template void name ## Pool::FreeItem(size_t index); \
00212 template void name ## Pool::CleanPool();
00213
00214 #endif