/* ****************************************************************************** Project: OWA HYDRAULIC Version: 2.2 Module: mempool.c Description: a simple fast poooled memory allocation package Authors: see AUTHORS Copyright: see AUTHORS License: see LICENSE Last Updated: 05/15/2019 This module is based code by Steve Hill in Graphics Gems III, David Kirk (ed.), Academic Press, Boston, MA, 1992 ****************************************************************************** */ #include #include "mempool.h" /* ** ALLOC_BLOCK_SIZE - adjust this size to suit your installation - it ** should be reasonably large otherwise you will be mallocing a lot. */ #define ALLOC_BLOCK_SIZE 64000 /*(62*1024)*/ struct MemBlock { struct MemBlock *next; // Next block char *block, // Start of block *free, // Next free position in block *end; // block + block size }; struct Mempool { struct MemBlock *first; struct MemBlock *current; }; static struct MemBlock* createMemBlock() { struct MemBlock* memBlock =(MemBlock *) malloc(sizeof(struct MemBlock)); if (memBlock) { memBlock->block =(char*) malloc(ALLOC_BLOCK_SIZE * sizeof(char)); if (memBlock->block == NULL) { free(memBlock); return NULL; } memBlock->free = memBlock->block; memBlock->next = NULL; memBlock->end = memBlock->block + ALLOC_BLOCK_SIZE; } return memBlock; } static void deleteMemBlock(struct MemBlock* memBlock) { free(memBlock->block); free(memBlock); } struct Mempool * mempool_create() { struct Mempool *mempool; mempool = (struct Mempool *)malloc(sizeof(struct Mempool)); if (mempool == NULL) return NULL; mempool->first = createMemBlock(); mempool->current = mempool->first; if (mempool->first == NULL) return NULL; return mempool; } void mempool_delete(struct Mempool *mempool) { if (mempool == NULL) return; while (mempool->first) { mempool->current = mempool->first->next; deleteMemBlock(mempool->first); mempool->first = mempool->current; } free(mempool); mempool = NULL; } void mempool_reset(struct Mempool *mempool) { mempool->current = mempool->first; mempool->current->free = mempool->current->block; } char * mempool_alloc(struct Mempool *mempool, size_t size) { char* ptr; /* ** Align to 4 byte boundary - should be ok for most machines. ** Change this if your machine has weird alignment requirements. */ size = (size + 3) & 0xfffffffc; if (!mempool->current) return NULL; ptr = mempool->current->free; mempool->current->free += size; // Check if the current block is exhausted if (mempool->current->free >= mempool->current->end) { // Is the next block already allocated? if (mempool->current->next) { // re-use block mempool->current->next->free = mempool->current->next->block; mempool->current = mempool->current->next; } else { // extend the pool with a new block mempool->current->next = createMemBlock(); if (!mempool->current->next) return NULL; mempool->current = mempool->current->next; } // set ptr to the first location in the next block ptr = mempool->current->free; mempool->current->free += size; } // Return pointer to allocated memory return ptr; }