summaryrefslogtreecommitdiff
path: root/src/oldpool.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/oldpool.h')
-rw-r--r--src/oldpool.h175
1 files changed, 163 insertions, 12 deletions
diff --git a/src/oldpool.h b/src/oldpool.h
index 80e121cb6..5e5b53c59 100644
--- a/src/oldpool.h
+++ b/src/oldpool.h
@@ -29,14 +29,14 @@ protected:
const char* name; ///< Name of the pool (just for debugging)
- uint max_blocks; ///< The max amount of blocks this pool can have
- uint block_size_bits; ///< The size of each block in bits
- uint item_size; ///< How many bytes one block is
+ const uint max_blocks; ///< The max amount of blocks this pool can have
+ const uint block_size_bits; ///< The size of each block in bits
+ const uint item_size; ///< How many bytes one block is
/// Pointer to a function that is called after a new block is added
- OldMemoryPoolNewBlock *new_block_proc;
+ const OldMemoryPoolNewBlock *new_block_proc;
/// Pointer to a function that is called to clean a block
- OldMemoryPoolCleanBlock *clean_block_proc;
+ const OldMemoryPoolCleanBlock *clean_block_proc;
uint current_blocks; ///< How many blocks we have in our pool
uint total_items; ///< How many items we now have in this pool
@@ -44,20 +44,45 @@ protected:
public:
byte **blocks; ///< An array of blocks (one block hold all the items)
- inline uint GetSize()
+ /**
+ * Get the size of this pool, i.e. the total number of items you
+ * can put into it at the current moment; the pool might still
+ * be able to increase the size of the pool.
+ * @return the size of the pool
+ */
+ inline uint GetSize() const
{
return this->total_items;
}
- inline bool CanAllocateMoreBlocks()
+ /**
+ * Can this pool allocate more blocks, i.e. is the maximum amount
+ * of allocated blocks not yet reached?
+ * @return the if and only if the amount of allocable blocks is
+ * less than the amount of allocated blocks.
+ */
+ inline bool CanAllocateMoreBlocks() const
{
return this->current_blocks < this->max_blocks;
}
- inline uint GetBlockCount()
+ /**
+ * Get the maximum number of allocable blocks.
+ * @return the numebr of blocks
+ */
+ inline uint GetBlockCount() const
{
return this->current_blocks;
}
+
+ /**
+ * Get the name of this pool.
+ * @return the name
+ */
+ inline const char *GetName() const
+ {
+ return this->name;
+ }
};
template <typename T>
@@ -66,7 +91,13 @@ struct OldMemoryPool : public OldMemoryPoolBase {
OldMemoryPoolNewBlock *new_block_proc, OldMemoryPoolCleanBlock *clean_block_proc) :
OldMemoryPoolBase(name, max_blocks, block_size_bits, item_size, new_block_proc, clean_block_proc) {}
- inline T *Get(uint index)
+ /**
+ * Get the pool entry at the given index.
+ * @param index the index into the pool
+ * @pre index < this->GetSize()
+ * @return the pool entry.
+ */
+ inline T *Get(uint index) const
{
assert(index < this->GetSize());
return (T*)(this->blocks[index >> this->block_size_bits] +
@@ -99,11 +130,9 @@ static inline bool AddBlockIfNeeded(OldMemoryPoolBase *array, uint index) { retu
template <typename T, OldMemoryPool<T> *Tpool>
static void PoolNewBlock(uint start_item)
{
- /* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
- * TODO - This is just a temporary stage, this will be removed. */
for (T *t = Tpool->Get(start_item); t != NULL; t = (t->index + 1U < Tpool->GetSize()) ? Tpool->Get(t->index + 1U) : NULL) {
+ t = new (t) T();
t->index = start_item++;
- t->PreInit();
}
}
@@ -125,6 +154,128 @@ static void PoolCleanBlock(uint start_item, uint end_item)
}
+/**
+ * Generalization for all pool items that are saved in the savegame.
+ * It specifies all the mechanics to access the pool easily.
+ */
+template <typename T, typename Tid, OldMemoryPool<T> *Tpool>
+struct PoolItem {
+ /**
+ * The pool-wide index of this object.
+ */
+ Tid index;
+
+ /**
+ * We like to have the correct class destructed.
+ */
+ virtual ~PoolItem()
+ {
+ }
+
+ /**
+ * Called on each object when the pool is being destroyed, so one
+ * can free allocated memory without the need for freeing for
+ * example orders.
+ */
+ virtual void QuickFree()
+ {
+ }
+
+ /**
+ * An overriden version of new that allocates memory on the pool.
+ * @param size the size of the variable (unused)
+ * @return the memory that is 'allocated'
+ */
+ void *operator new (size_t size)
+ {
+ return AllocateRaw();
+ }
+
+ /**
+ * 'Free' the memory allocated by the overriden new.
+ * @param p the memory to 'free'
+ */
+ void operator delete(void *p)
+ {
+ }
+
+ /**
+ * An overriden version of new, so you can directly allocate a new object with
+ * the correct index when one is loading the savegame.
+ * @param size the size of the variable (unused)
+ * @param index the index of the object
+ * @return the memory that is 'allocated'
+ */
+ void *operator new (size_t size, int index)
+ {
+ if (!Tpool->AddBlockIfNeeded(index)) error("%s: failed loading savegame: too many %s", Tpool->GetName(), Tpool->GetName());
+
+ return Tpool->Get(index);
+ }
+
+ /**
+ * 'Free' the memory allocated by the overriden new.
+ * @param p the memory to 'free'
+ * @param index the original parameter given to create the memory
+ */
+ void operator delete(void *p, int index)
+ {
+ }
+
+ /**
+ * An overriden version of new, so you can use the vehicle instance
+ * instead of a newly allocated piece of memory.
+ * @param size the size of the variable (unused)
+ * @param pn the already existing object to use as 'storage' backend
+ * @return the memory that is 'allocated'
+ */
+ void *operator new(size_t size, T *pn)
+ {
+ return pn;
+ }
+
+ /**
+ * 'Free' the memory allocated by the overriden new.
+ * @param p the memory to 'free'
+ * @param pn the pointer that was given to 'new' on creation.
+ */
+ void operator delete(void *p, T *pn)
+ {
+ }
+
+ /**
+ * Is this a valid object or not?
+ * @return true if and only if it is valid
+ */
+ virtual bool IsValid() const
+ {
+ return false;
+ }
+
+private:
+ /**
+ * Allocate a pool item; possibly allocate a new block in the pool.
+ * @return the allocated pool item (or NULL when the pool is full).
+ */
+ static T *AllocateRaw()
+ {
+ for (T *t = Tpool->Get(0); t != NULL; t = (t->index + 1U < Tpool->GetSize()) ? Tpool->Get(t->index + 1U) : NULL) {
+ if (!t->IsValid()) {
+ Tid index = t->index;
+
+ memset(t, 0, sizeof(T));
+ t->index = index;
+ return t;
+ }
+ }
+
+ /* Check if we can add a block to the pool */
+ if (Tpool->AddBlockToPool()) return AllocateRaw();
+
+ return NULL;
+ }
+};
+
#define OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \
enum { \