alloc/chunked: actually free the memory at destructor time

This commit is contained in:
Danny Robson 2021-04-09 15:40:36 +10:00
parent 8339c55baa
commit fc2d9e77c1
2 changed files with 35 additions and 16 deletions

View File

@ -26,14 +26,14 @@ chunked::chunked (std::size_t initial_size)
chunked::chunked (std::size_t initial_size, std::size_t _chunk_size) chunked::chunked (std::size_t initial_size, std::size_t _chunk_size)
: m_chunk (_chunk_size) : m_chunk (_chunk_size)
{ {
m_chunk = cruft::max (m_chunk, sizeof (node_t)); m_chunk = cruft::max (m_chunk, sizeof (allocation_t));
auto const initial_arenas = cruft::divup (initial_size, m_chunk); auto const initial_arenas = cruft::divup (initial_size, m_chunk);
m_data.resize (initial_arenas); m_data.resize (initial_arenas);
for (auto &i: m_data) { for (auto &i: m_data) {
i.data = new std::byte[m_chunk]; i.head = i.remain.data = new std::byte[m_chunk];
*i.node = { *i.remain.node = {
.size = m_chunk, .size = m_chunk,
.next = nullptr .next = nullptr
}; };
@ -41,24 +41,32 @@ chunked::chunked (std::size_t initial_size, std::size_t _chunk_size)
} }
//-----------------------------------------------------------------------------
chunked::~chunked () noexcept
{
for (auto &i: m_data)
delete [] i.head;
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
void* void*
chunked::do_allocate (std::size_t size, std::size_t alignment) chunked::do_allocate (std::size_t size, std::size_t alignment)
{ {
// Find a chunk that can service this allocation. // Find a chunk that can service this allocation.
for (auto &i: m_data) { for (auto &i: m_data) {
if (i.node->size < size + alignment) if (i.remain.node->size < size + alignment)
continue; continue;
auto base = cruft::align::up (i.data, alignment); auto base = cruft::align::up (i.remain.data, alignment);
std::byte* newbase = base + size; std::byte* newbase = base + size;
if (newbase > i.data + i.node->size) if (newbase > i.remain.data + i.remain.node->size)
continue; continue;
std::size_t newsize = i.data + i.node->size - newbase; std::size_t newsize = i.remain.data + i.remain.node->size - newbase;
i.data = newbase; i.remain.data = newbase;
i.node->size = newsize; i.remain.node->size = newsize;
return base; return base;
} }
@ -66,9 +74,14 @@ chunked::do_allocate (std::size_t size, std::size_t alignment)
// No chunk was found. We need to allocate a new chunk of at least enough size. // No chunk was found. We need to allocate a new chunk of at least enough size.
std::size_t allocation_size = cruft::max (size + alignment, m_chunk); std::size_t allocation_size = cruft::max (size + alignment, m_chunk);
std::unique_ptr<std::byte[]> ptr (new std::byte[allocation_size]); std::unique_ptr<std::byte[]> ptr (new std::byte[allocation_size]);
m_data.push_back (arena { ptr.get () }); m_data.push_back (
m_data.back ().node->size = allocation_size; ::cruft::alloc::chunked::arena {
m_data.back ().node->next = m_data.back ().node; .head = ptr.get (),
.remain = { .data = ptr.get (), },
}
);
m_data.back ().remain.node->size = allocation_size;
m_data.back ().remain.node->next = m_data.back ().remain.node;
ptr.release (); ptr.release ();
return do_allocate (size, alignment); return do_allocate (size, alignment);
} }

View File

@ -65,6 +65,7 @@ namespace cruft::alloc {
explicit chunked (std::size_t initial_size); explicit chunked (std::size_t initial_size);
chunked (std::size_t initial_size, std::size_t chunk_size); chunked (std::size_t initial_size, std::size_t chunk_size);
~chunked () noexcept;
private: private:
void* do_allocate ( void* do_allocate (
@ -82,14 +83,19 @@ namespace cruft::alloc {
std::size_t m_chunk; std::size_t m_chunk;
struct node_t { struct allocation_t {
std::size_t size; std::size_t size;
node_t* next; allocation_t* next;
}; };
union arena { union node {
std::byte *data; std::byte *data;
node_t *node; allocation_t *node;
};
struct arena {
std::byte *head;
node remain;
}; };
std::vector<arena> m_data; std::vector<arena> m_data;