From 62a7948af0ca9eb3b190a54918201e1075edcbbc Mon Sep 17 00:00:00 2001 From: smatz Date: Fri, 22 May 2009 15:13:50 +0000 Subject: (svn r16378) -Codechange: replace OldPool with simpler Pool. Compilation time, binary size and run time (with asserts disabled) should be improved --- src/core/pool_func.hpp | 139 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 src/core/pool_func.hpp (limited to 'src/core/pool_func.hpp') diff --git a/src/core/pool_func.hpp b/src/core/pool_func.hpp new file mode 100644 index 000000000..df9e2692f --- /dev/null +++ b/src/core/pool_func.hpp @@ -0,0 +1,139 @@ +/* $Id$ */ + +/** @file pool_func.hpp Some methods of Pool are placed here in order to reduce compilation time and binary size. */ + +#ifndef POOL_FUNC_HPP +#define POOL_FUNC_HPP + +#include "alloc_func.hpp" +#include "mem_func.hpp" +#include "pool.hpp" + +#define DEFINE_POOL_METHOD(type) \ + template \ + type Pool + +DEFINE_POOL_METHOD(inline)::Pool(const char *name) : + name(name), + size(0), + first_free(0), + first_unused(0), + items(0), + cleaning(false), + data(NULL) +{ } + +DEFINE_POOL_METHOD(inline void)::ResizeFor(size_t index) +{ + assert(index >= this->size); + assert(index < Tmax_size); + + size_t new_size = min(Tmax_size, Align(index + 1, Tgrowth_step)); + + this->data = ReallocT(this->data, new_size); + MemSetT(this->data + this->size, 0, new_size - this->size); + + this->size = new_size; +} + +DEFINE_POOL_METHOD(inline size_t)::FindFirstFree() +{ + size_t index = this->first_free; + + for (; index < this->first_unused; index++) { + if (this->data[index] == NULL) return index; + } + + if (index < this->size) { + return index; + } + + assert(index == this->size); + assert(this->first_unused == this->size); + + if (index < Tmax_size) { + this->ResizeFor(index); + return index; + } + + assert(this->items == Tmax_size); + + return NO_FREE_ITEM; +} + +DEFINE_POOL_METHOD(inline void *)::AllocateItem(size_t size, size_t index) +{ + assert(this->data[index] == NULL); + + this->first_unused = max(this->first_unused, index + 1); + this->items++; + + Titem *item = this->data[index] = (Titem *)CallocT(size); + item->index = (uint)index; + return item; +} + +DEFINE_POOL_METHOD(void *)::GetNew(size_t size) +{ + size_t index = this->FindFirstFree(); + + if (index == NO_FREE_ITEM) { + error("%s: no more free items", this->name); + } + + this->first_free = index + 1; + return this->AllocateItem(size, index); +} + +DEFINE_POOL_METHOD(void *)::GetNew(size_t size, size_t index) +{ + if (index >= Tmax_size) { + usererror("failed loading savegame: %s index " PRINTF_SIZE " out of range (" PRINTF_SIZE ")", this->name, index, Tmax_size); + } + + if (index >= this->size) this->ResizeFor(index); + + if (this->data[index] != NULL) { + usererror("failed loading savegame: %s index " PRINTF_SIZE " already in use", this->name, index); + } + + return this->AllocateItem(size, index); +} + +DEFINE_POOL_METHOD(void)::FreeItem(size_t index) +{ + assert(index < this->size); + assert(this->data[index] != NULL); + free(this->data[index]); + this->data[index] = NULL; + this->first_free = min(this->first_free, index); + this->items--; +} + +DEFINE_POOL_METHOD(void)::CleanPool() +{ + this->cleaning = true; + for (size_t i = 0; i < this->first_unused; i++) { + delete this->Get(i); // 'delete NULL;' is very valid + } + assert(this->items == 0); + free(this->data); + this->first_unused = this->first_free = this->size = 0; + this->data = NULL; + this->cleaning = false; +} + +#undef DEFINE_POOL_METHOD + +/** + * Force instantiation of pool methods so we don't get linker errors. + * Only methods accessed from methods defined in pool.hpp need to be + * forcefully instantiated. + */ +#define INSTANTIATE_POOL_METHODS(name) \ + template void * name ## Pool::GetNew(size_t size); \ + template void * name ## Pool::GetNew(size_t size, size_t index); \ + template void name ## Pool::FreeItem(size_t index); \ + template void name ## Pool::CleanPool(); + +#endif /* POOL_FUNC_HPP */ -- cgit v1.2.3-54-g00ecf