1 #include "yacas/mempool.h"
2
3 #include <algorithm>
4 #include <cassert>
5
MemPool(unsigned block_size,unsigned no_blocks)6 MemPool::MemPool(unsigned block_size, unsigned no_blocks) :
7 _block_size(std::max(static_cast<std::size_t>(block_size), sizeof(void*))),
8 _no_blocks(no_blocks),
9 _no_free_blocks(no_blocks),
10 _no_initialized_blocks(0),
11 _pool(new std::uint8_t[_block_size * _no_blocks]),
12 _next_free_block(_pool),
13 _next_pool(nullptr)
14 {
15 }
16
~MemPool()17 MemPool::~MemPool() noexcept
18 {
19 assert(_no_free_blocks == _no_blocks);
20
21 delete _next_pool;
22 delete[] _pool;
23 }
24
alloc()25 void* MemPool::alloc()
26 {
27 if (_no_free_blocks) {
28 if (_no_initialized_blocks <= _no_blocks - _no_free_blocks) {
29 std::uint8_t* p = _pool + _no_initialized_blocks * _block_size;
30 *reinterpret_cast<std::uint8_t**>(p) = p + _block_size;
31 _no_initialized_blocks += 1;
32 }
33
34 void* ret = _next_free_block;
35
36 if (--_no_free_blocks)
37 _next_free_block =
38 *reinterpret_cast<std::uint8_t**>(_next_free_block);
39 else
40 _next_free_block = nullptr;
41
42 return ret;
43 }
44
45 if (!_next_pool)
46 _next_pool = new MemPool(_block_size, _no_blocks);
47
48 return _next_pool->alloc();
49 }
50
free(void * p)51 void MemPool::free(void* p) noexcept
52 {
53 if (p >= _pool && p < _pool + _block_size * _no_blocks) {
54 if (_next_free_block) {
55 *reinterpret_cast<std::uint8_t**>(p) = _next_free_block;
56 _next_free_block = static_cast<std::uint8_t*>(p);
57 } else {
58 *reinterpret_cast<std::uint8_t**>(p) = _pool + _no_blocks;
59 _next_free_block = static_cast<std::uint8_t*>(p);
60 }
61 _no_free_blocks += 1;
62 } else {
63 _next_pool->free(p);
64 }
65 }
66