mbed OS5
Fork of UIPEthernet by
Diff: uitility/mempool.cpp
- Revision:
- 0:5350a66d5279
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uitility/mempool.cpp Mon Sep 15 11:12:30 2014 +0000 @@ -0,0 +1,190 @@ +/* + 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 + +/** + * @brief + * @note + * @param + * @retval + */ +MemoryPool::MemoryPool(memaddress start, memaddress size) { + memset(&blocks[0], 0, sizeof(blocks)); + blocks[POOLSTART].begin = start; + blocks[POOLSTART].size = 0; + blocks[POOLSTART].nextblock = NOBLOCK; + poolsize = size; +} + +/** + * @brief + * @note + * @param + * @retval + */ +memhandle MemoryPool::allocBlock(memaddress size) { + memblock* best = NULL; + memhandle cur = POOLSTART; + memblock* block = &blocks[POOLSTART]; + memaddress bestsize = poolsize + 1; + + do + { + memhandle next = block->nextblock; + memaddress freesize = (next == NOBLOCK ? blocks[POOLSTART].begin + poolsize : 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 MEMBLOCK_MV + memblock_mv_cb(dest, *src, nextblock->size); +#endif + *src = dest; + } + + block = nextblock; + } + + if(blocks[POOLSTART].begin + poolsize - block->begin - block->size >= size) + best = block; + else + goto notfound; + } + +found: + { + block = &blocks[POOLOFFSET]; + for(cur = POOLOFFSET; cur < 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 MemoryPool::freeBlock(memhandle handle) { + 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 MemoryPool::resizeBlock(memhandle handle, memaddress position) { + memblock* block = &blocks[handle]; + block->begin += position; + block->size -= position; +} + +/** + * @brief + * @note + * @param + * @retval + */ +void MemoryPool::resizeBlock(memhandle handle, memaddress position, memaddress size) { + memblock* block = &blocks[handle]; + block->begin += position; + block->size = size; +} + +/** + * @brief + * @note + * @param + * @retval + */ +memaddress MemoryPool::blockSize(memhandle handle) { + return blocks[handle].size; +}