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