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)
: 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);
m_data.resize (initial_arenas);
for (auto &i: m_data) {
i.data = new std::byte[m_chunk];
*i.node = {
i.head = i.remain.data = new std::byte[m_chunk];
*i.remain.node = {
.size = m_chunk,
.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*
chunked::do_allocate (std::size_t size, std::size_t alignment)
{
// Find a chunk that can service this allocation.
for (auto &i: m_data) {
if (i.node->size < size + alignment)
if (i.remain.node->size < size + alignment)
continue;
auto base = cruft::align::up (i.data, alignment);
auto base = cruft::align::up (i.remain.data, alignment);
std::byte* newbase = base + size;
if (newbase > i.data + i.node->size)
if (newbase > i.remain.data + i.remain.node->size)
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.node->size = newsize;
i.remain.data = newbase;
i.remain.node->size = newsize;
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.
std::size_t allocation_size = cruft::max (size + alignment, m_chunk);
std::unique_ptr<std::byte[]> ptr (new std::byte[allocation_size]);
m_data.push_back (arena { ptr.get () });
m_data.back ().node->size = allocation_size;
m_data.back ().node->next = m_data.back ().node;
m_data.push_back (
::cruft::alloc::chunked::arena {
.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 ();
return do_allocate (size, alignment);
}

View File

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