Skip to content

Commit

Permalink
Improve array allocations in memory_pool_collection
Browse files Browse the repository at this point in the history
Now it uses the shared stack directly and supports free lists that do not support array allocations natively.

Also change internal requirements for those free lists.
  • Loading branch information
foonathan committed Apr 16, 2016
1 parent 7286cb6 commit a555ddf
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 17 deletions.
9 changes: 6 additions & 3 deletions include/foonathan/memory/detail/small_free_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ namespace foonathan { namespace memory
// pre: !empty()
void* allocate() FOONATHAN_NOEXCEPT;

// must not be called
// always returns nullptr, because array allocations are not supported
void* allocate(std::size_t) FOONATHAN_NOEXCEPT
{
return nullptr;
Expand All @@ -86,8 +86,11 @@ namespace foonathan { namespace memory
// deallocates the node previously allocated via allocate()
void deallocate(void *node) FOONATHAN_NOEXCEPT;

// must not be called
void deallocate(void *, std::size_t) FOONATHAN_NOEXCEPT {}
// forwards to insert()
void deallocate(void *mem, std::size_t size) FOONATHAN_NOEXCEPT
{
insert(mem, size);
}

// hint for allocate() to be prepared to allocate n nodes
// it searches for a chunk that has n nodes free
Expand Down
38 changes: 24 additions & 14 deletions include/foonathan/memory/memory_pool_collection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,14 @@ namespace foonathan { namespace memory
detail::check_allocation_size<bad_node_size>(node_size, [&]{return max_node_size();}, info());
auto& pool = pools_.get(node_size);
if (pool.empty())
reserve_impl(pool, def_capacity());
return pool.allocate();
{
auto block = reserve_memory(pool, def_capacity());
pool.insert(block.memory, block.size);
}

auto mem = pool.allocate();
FOONATHAN_MEMORY_ASSERT(mem);
return mem;
}

/// \effects Allocates an \concept{concept_array,array} of nodes by searching for \c n continuous nodes on the appropriate free list and removing them.
Expand All @@ -141,16 +147,20 @@ namespace foonathan { namespace memory
detail::check_allocation_size<bad_node_size>(node_size, [&]{return max_node_size();}, info());

auto& pool = pools_.get(node_size);
if (pool.empty())
reserve_impl(pool, def_capacity());
auto mem = pool.allocate(count * node_size);

// try allocating if not empty
// for pools without array allocation support, allocate() will always return nullptr
auto mem = pool.empty() ? nullptr : pool.allocate(count * node_size);
if (!mem)
{
reserve_impl(pool, count * node_size);
mem = pool.allocate(count * node_size);
if (!mem)
FOONATHAN_THROW(bad_array_size(info(), count * node_size, next_capacity()));
// use stack for allocation
detail::check_allocation_size<bad_array_size>(count * node_size,
[&]{return next_capacity() - pool.alignment() + 1;},
info());
mem = reserve_memory(pool, count * node_size).memory;
FOONATHAN_MEMORY_ASSERT(mem);
}

return mem;
}

Expand All @@ -167,8 +177,9 @@ namespace foonathan { namespace memory
/// i.e. either this allocator object or a new object created by moving this to it.
void deallocate_array(void *ptr, std::size_t count, std::size_t node_size) FOONATHAN_NOEXCEPT
{
FOONATHAN_MEMORY_ASSERT_MSG(PoolType::value, "array allocations not supported");
auto& pool = pools_.get(node_size);
// deallocate array
// for pools without array allocation support, this will simply forward to insert()
pool.deallocate(ptr, count * node_size);
}

Expand All @@ -183,7 +194,7 @@ namespace foonathan { namespace memory
{
FOONATHAN_MEMORY_ASSERT_MSG(node_size <= max_node_size(), "node_size too big");
auto& pool = pools_.get(node_size);
reserve_impl(pool, capacity);
reserve_memory(pool, capacity);
}

/// \returns The maximum node size for which is a free list.
Expand Down Expand Up @@ -249,7 +260,7 @@ namespace foonathan { namespace memory
return static_cast<const char*>(block.memory) + block.size;
}

void reserve_impl(typename pool_type::type &pool, std::size_t capacity)
memory_block reserve_memory(typename pool_type::type &pool, std::size_t capacity)
{
auto mem = stack_.allocate(block_end(), capacity, detail::max_alignment);
if (!mem)
Expand All @@ -272,8 +283,7 @@ namespace foonathan { namespace memory
mem = stack_.allocate(block_end(), capacity, detail::max_alignment);
FOONATHAN_MEMORY_ASSERT(mem);
}
// insert new
pool.insert(mem, capacity);
return {mem, capacity};
}

memory_arena<allocator_type, false> arena_;
Expand Down

0 comments on commit a555ddf

Please sign in to comment.