tron@2186: /* $Id$ */ tron@2186: belugas@6351: /** @file oldpool.h */ belugas@6351: matthijs@5224: #ifndef OLDPOOL_H matthijs@5224: #define OLDPOOL_H truelight@1259: truelight@1259: /* The function that is called after a new block is added truelight@1259: start_item is the first item of the new made block */ matthijs@5216: typedef void OldMemoryPoolNewBlock(uint start_item); peter1138@3585: /* The function that is called before a block is cleaned up */ matthijs@5216: typedef void OldMemoryPoolCleanBlock(uint start_item, uint end_item); truelight@1259: truelight@1259: /** matthijs@5216: * Stuff for dynamic vehicles. Use the wrappers to access the OldMemoryPool truelight@1259: * please try to avoid manual calls! truelight@1259: */ rubidium@7375: struct OldMemoryPoolBase { rubidium@7375: void CleanPool(); rubidium@7375: bool AddBlockToPool(); rubidium@7375: bool AddBlockIfNeeded(uint index); rubidium@7375: rubidium@7375: protected: rubidium@7375: OldMemoryPoolBase(const char *name, uint max_blocks, uint block_size_bits, uint item_size, rubidium@7375: OldMemoryPoolNewBlock *new_block_proc, OldMemoryPoolCleanBlock *clean_block_proc) : rubidium@7375: name(name), max_blocks(max_blocks), block_size_bits(block_size_bits), item_size(item_size), rubidium@7375: new_block_proc(new_block_proc), clean_block_proc(clean_block_proc), current_blocks(0), rubidium@7375: total_items(0), blocks(NULL) {} rubidium@7375: rubidium@5587: const char* name; ///< Name of the pool (just for debugging) truelight@1259: rubidium@5587: uint max_blocks; ///< The max amount of blocks this pool can have rubidium@5587: uint block_size_bits; ///< The size of each block in bits rubidium@5587: uint item_size; ///< How many bytes one block is truelight@1259: peter1138@3173: /// Pointer to a function that is called after a new block is added matthijs@5216: OldMemoryPoolNewBlock *new_block_proc; peter1138@3585: /// Pointer to a function that is called to clean a block matthijs@5216: OldMemoryPoolCleanBlock *clean_block_proc; truelight@1259: peter1138@3173: uint current_blocks; ///< How many blocks we have in our pool peter1138@3173: uint total_items; ///< How many items we now have in this pool peter1138@3173: rubidium@7375: public: peter1138@3173: byte **blocks; ///< An array of blocks (one block hold all the items) rubidium@7375: rubidium@7375: inline uint GetSize() rubidium@7375: { rubidium@7375: return this->total_items; rubidium@7375: } rubidium@7375: rubidium@7375: inline bool CanAllocateMoreBlocks() rubidium@7375: { rubidium@7375: return this->current_blocks < this->max_blocks; rubidium@7375: } rubidium@7375: rubidium@7375: inline uint GetBlockCount() rubidium@7375: { rubidium@7375: return this->current_blocks; rubidium@7375: } rubidium@7375: }; rubidium@7375: rubidium@7375: template rubidium@7375: struct OldMemoryPool : public OldMemoryPoolBase { rubidium@7375: OldMemoryPool(const char *name, uint max_blocks, uint block_size_bits, uint item_size, rubidium@7375: OldMemoryPoolNewBlock *new_block_proc, OldMemoryPoolCleanBlock *clean_block_proc) : rubidium@7375: OldMemoryPoolBase(name, max_blocks, block_size_bits, item_size, new_block_proc, clean_block_proc) {} rubidium@7375: rubidium@7375: inline T *Get(uint index) rubidium@7375: { rubidium@7375: assert(index < this->GetSize()); rubidium@7375: return (T*)(this->blocks[index >> this->block_size_bits] + rubidium@7375: (index & ((1 << this->block_size_bits) - 1)) * sizeof(T)); rubidium@7375: } truelight@1259: }; truelight@1259: truelight@1259: /** truelight@1259: * Those are the wrappers: truelight@1259: * CleanPool cleans the pool up, but you can use AddBlockToPool directly again truelight@1259: * (no need to call CreatePool!) truelight@1259: * AddBlockToPool adds 1 more block to the pool. Returns false if there is no truelight@1259: * more room truelight@1259: */ rubidium@7375: static inline void CleanPool(OldMemoryPoolBase *array) { array->CleanPool(); } rubidium@7375: static inline bool AddBlockToPool(OldMemoryPoolBase *array) { return array->AddBlockToPool(); } truelight@1259: truelight@1259: /** truelight@1259: * Adds blocks to the pool if needed (and possible) till index fits inside the pool truelight@1259: * truelight@1259: * @return Returns false if adding failed truelight@1259: */ rubidium@7375: static inline bool AddBlockIfNeeded(OldMemoryPoolBase *array, uint index) { return array->AddBlockIfNeeded(index); } truelight@1259: tron@4970: matthijs@5216: #define OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \ tron@4970: enum { \ tron@4970: name##_POOL_BLOCK_SIZE_BITS = block_size_bits, \ tron@4970: name##_POOL_MAX_BLOCKS = max_blocks \ tron@4970: }; tron@4970: tron@4970: matthijs@5216: #define OLD_POOL_ACCESSORS(name, type) \ rubidium@7375: static inline type* Get##name(uint index) { return _##name##_pool.Get(index); } \ rubidium@7375: static inline uint Get##name##PoolSize() { return _##name##_pool.GetSize(); } tron@4970: tron@4970: matthijs@5216: #define DECLARE_OLD_POOL(name, type, block_size_bits, max_blocks) \ matthijs@5216: OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \ rubidium@7375: extern OldMemoryPool _##name##_pool; \ matthijs@5216: OLD_POOL_ACCESSORS(name, type) tron@4970: tron@4970: matthijs@5216: #define DEFINE_OLD_POOL(name, type, new_block_proc, clean_block_proc) \ rubidium@7375: OldMemoryPool _##name##_pool( \ tron@4970: #name, name##_POOL_MAX_BLOCKS, name##_POOL_BLOCK_SIZE_BITS, sizeof(type), \ rubidium@7375: new_block_proc, clean_block_proc); tron@4970: tron@4970: matthijs@5216: #define STATIC_OLD_POOL(name, type, block_size_bits, max_blocks, new_block_proc, clean_block_proc) \ matthijs@5216: OLD_POOL_ENUM(name, type, block_size_bits, max_blocks) \ matthijs@5216: static DEFINE_OLD_POOL(name, type, new_block_proc, clean_block_proc) \ matthijs@5216: OLD_POOL_ACCESSORS(name, type) tron@4970: matthijs@5224: #endif /* OLDPOOL_H */