123
Diff: utility/MemPool.cpp
- Revision:
- 9:a156d3de5647
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/utility/MemPool.cpp Tue Aug 27 15:01:10 2019 +0000 @@ -0,0 +1,192 @@ +/* + mempool.cpp - sleek implementation of a memory pool + Copyright (c) 2013 Norbert Truchsess <norbert.truchsess@t-online.de> + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "MemPool.h" +#include <string.h> + +#define POOLOFFSET 1 + +struct memblock MemPool:: blocks[MEMPOOL_NUM_MEMBLOCKS + 1]; + +/** + * @brief + * @note + * @param + * @retval + */ +void MemPool::init() { + memset(&blocks[0], 0, sizeof(blocks)); + blocks[POOLSTART].begin = MEMPOOL_STARTADDRESS; + blocks[POOLSTART].size = 0; + blocks[POOLSTART].nextblock = NOBLOCK; +} + +/** + * @brief + * @note + * @param + * @retval + */ +memhandle MemPool::allocBlock(memaddress size) { + memblock* best = NULL; + memhandle cur = POOLSTART; + memblock* block = &blocks[POOLSTART]; + memaddress bestsize = MEMPOOL_SIZE + 1; + + do { + memhandle next = block->nextblock; + memaddress freesize = (next == NOBLOCK ? blocks[POOLSTART].begin + MEMPOOL_SIZE : blocks[next].begin) - + block->begin - + block->size; + if (freesize == size) { + best = &blocks[cur]; + goto found; + } + + if (freesize > size && freesize < bestsize) { + bestsize = freesize; + best = &blocks[cur]; + } + + if (next == NOBLOCK) { + if (best) + goto found; + else + goto collect; + } + + block = &blocks[next]; + cur = next; + } while (true); + +collect: + { + cur = POOLSTART; + block = &blocks[POOLSTART]; + + memhandle next; + while ((next = block->nextblock) != NOBLOCK) { + memaddress dest = block->begin + block->size; + memblock* nextblock = &blocks[next]; + memaddress* src = &nextblock->begin; + if (dest != *src) + { +#ifdef MEMPOOL_MEMBLOCK_MV + MEMPOOL_MEMBLOCK_MV(dest, *src, nextblock->size); +#endif + *src = dest; + } + + block = nextblock; + } + + if (blocks[POOLSTART].begin + MEMPOOL_SIZE - block->begin - block->size >= size) + best = block; + else + goto notfound; + } + +found: + { + block = &blocks[POOLOFFSET]; + for (cur = POOLOFFSET; cur < MEMPOOL_NUM_MEMBLOCKS + POOLOFFSET; cur++) { + if (block->size) { + block++; + continue; + } + + memaddress address = best->begin + best->size; +#ifdef MEMBLOCK_ALLOC + MEMBLOCK_ALLOC(address, size); +#endif + block->begin = address; + block->size = size; + block->nextblock = best->nextblock; + best->nextblock = cur; + return cur; + } + } + +notfound: + return NOBLOCK; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void MemPool::freeBlock(memhandle handle) { + if (handle == NOBLOCK) + return; + + memblock* b = &blocks[POOLSTART]; + + do { + memhandle next = b->nextblock; + if (next == handle) { + memblock* f = &blocks[next]; +#ifdef MEMBLOCK_FREE + MEMBLOCK_FREE(f->begin, f->size); +#endif + b->nextblock = f->nextblock; + f->size = 0; + f->nextblock = NOBLOCK; + return; + } + + if (next == NOBLOCK) + return; + b = &blocks[next]; + } while (true); +} + +/** + * @brief + * @note + * @param + * @retval + */ +void MemPool::resizeBlock(memhandle handle, memaddress position) { + memblock* block = &blocks[handle]; + block->begin += position; + block->size -= position; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void MemPool::resizeBlock(memhandle handle, memaddress position, memaddress size) { + memblock* block = &blocks[handle]; + block->begin += position; + block->size = size; +} + +/** + * @brief + * @note + * @param + * @retval + */ +memaddress MemPool::blockSize(memhandle handle) { + return blocks[handle].size; +}