1 #ifndef CRYPTO3_MEM_POOL_HPP
2 #define CRYPTO3_MEM_POOL_HPP
4 #include <nil/crypto3/utilities/types.hpp>
12 inline bool ptr_in_pool(
const void *pool_ptr,
size_t poolsize,
const void *buf_ptr,
size_t bufsize) {
13 const uintptr_t pool =
reinterpret_cast<uintptr_t
>(pool_ptr);
14 const uintptr_t buf =
reinterpret_cast<uintptr_t
>(buf_ptr);
15 return (buf >= pool) && (buf + bufsize <= pool + poolsize);
19 const size_t mod = n % alignment;
23 return alignment - mod;
40 memory_pool(uint8_t *pool,
size_t pool_size,
size_t page_size,
size_t min_alloc,
size_t max_alloc,
42 m_page_size(page_size),
43 m_min_alloc(min_alloc), m_max_alloc(max_alloc), m_align_bit(align_bit) {
44 if (pool ==
nullptr) {
45 throw std::invalid_argument(
"memory_pool pool was null");
48 if (m_min_alloc > m_max_alloc) {
49 throw std::invalid_argument(
"memory_pool min_alloc > max_alloc");
52 if (m_align_bit > 6) {
53 throw std::invalid_argument(
"memory_pool invalid align_bit");
60 m_pool_size = pool_size;
61 m_freelist.emplace_back(0, m_pool_size);
65 const size_t alignment = (1 << m_align_bit);
67 if (req > m_pool_size) {
70 if (req < m_min_alloc || req > m_max_alloc) {
74 std::lock_guard<std::mutex> lock(m_mutex);
76 auto best_fit = m_freelist.end();
78 for (
auto i = m_freelist.begin(); i != m_freelist.end(); ++i) {
80 if (i->second == req && (i->first % alignment) == 0) {
81 const size_t offset = i->first;
85 BOOST_ASSERT_MSG((
reinterpret_cast<uintptr_t
>(m_pool) + offset) % alignment == 0,
86 "Returning correctly aligned pointer");
88 return m_pool + offset;
91 if (((best_fit == m_freelist.end()) || (best_fit->second > i->second)) &&
97 if (best_fit != m_freelist.end()) {
98 const size_t offset = best_fit->first;
102 best_fit->first += req + alignment_padding;
103 best_fit->second -= req + alignment_padding;
106 if (alignment_padding) {
114 if (best_fit->second == 0) {
115 best_fit->first = offset;
116 best_fit->second = alignment_padding;
118 m_freelist.insert(best_fit, std::make_pair(offset, alignment_padding));
122 clear_mem(m_pool + offset + alignment_padding, req);
124 BOOST_ASSERT_MSG((
reinterpret_cast<uintptr_t
>(m_pool) + offset + alignment_padding) % alignment ==
126 "Returning correctly aligned pointer");
128 return m_pool + offset + alignment_padding;
139 std::memset(p, 0, n);
141 std::lock_guard<std::mutex> lock(m_mutex);
143 const size_t start =
static_cast<uint8_t *
>(p) - m_pool;
145 auto comp = [](std::pair<size_t, size_t> x, std::pair<size_t, size_t> y) {
return x.first < y.first; };
147 auto i = std::lower_bound(m_freelist.begin(), m_freelist.end(), std::make_pair(start, 0), comp);
150 if (i != m_freelist.end() &&
152 start + n == i->first) {
159 if (i != m_freelist.begin()) {
160 auto prev = std::prev(i);
162 if (prev->first + prev->second == start) {
168 prev->second += i->second;
175 m_freelist.insert(i, std::make_pair(start, n));
186 const size_t m_page_size = 0;
187 const size_t m_min_alloc = 0;
188 const size_t m_max_alloc = 0;
189 const uint8_t m_align_bit = 0;
193 std::vector<std::pair<size_t, size_t>> m_freelist;
194 uint8_t *m_pool =
nullptr;
195 size_t m_pool_size = 0;
Definition: memory_pool.hpp:27
memory_pool & operator=(const memory_pool &)=delete
void * allocate(size_t req)
Definition: memory_pool.hpp:64
memory_pool(const memory_pool &)=delete
memory_pool(uint8_t *pool, size_t pool_size, size_t page_size, size_t min_alloc, size_t max_alloc, uint8_t align_bit)
Definition: memory_pool.hpp:40
bool deallocate(void *p, std::size_t n) BOOST_NOEXCEPT
Definition: memory_pool.hpp:134
size_t padding_for_alignment(size_t n, size_t alignment)
Definition: memory_pool.hpp:18
bool ptr_in_pool(const void *pool_ptr, size_t poolsize, const void *buf_ptr, size_t bufsize)
Definition: memory_pool.hpp:12
void clear_mem(T *ptr, size_t n)
Definition: memory_operations.hpp:175