memory
Typedefs | Member Functions
memory_pool_collection< PoolType, BucketDistribution, BlockOrRawAllocator > Class Template Reference

Detailed Description

template<class PoolType, class BucketDistribution, class BlockOrRawAllocator = default_allocator>
class foonathan::memory::memory_pool_collection< PoolType, BucketDistribution, BlockOrRawAllocator >

A stateful RawAllocator that behaves as a collection of multiple memory_pool objects.

It maintains a list of multiple free lists, whose types are controlled via the PoolType tags defined in memory_pool_type.hpp, each of a different size as defined in the BucketDistribution (identity_buckets or log2_buckets). Allocating a node of given size will use the appropriate free list.
This allocator is ideal for node allocations in any order but with a predefined set of sizes, not only one size like memory_pool.

Typedefs

using allocator_type = make_block_allocator_t< BlockOrRawAllocator >
 
using pool_type = PoolType
 
using bucket_distribution = BucketDistribution
 

Member Functions

template<typename... Args>
 memory_pool_collection (std::size_t max_node_size, std::size_t block_size, Args &&... args)
 
 ~memory_pool_collection () noexcept=default
 
void * allocate_node (std::size_t node_size)
 
void * try_allocate_node (std::size_t node_size) noexcept
 
void * allocate_array (std::size_t count, std::size_t node_size)
 
void * try_allocate_array (std::size_t count, std::size_t node_size) noexcept
 
void deallocate_node (void *ptr, std::size_t node_size) noexcept
 
bool try_deallocate_node (void *ptr, std::size_t node_size) noexcept
 
void deallocate_array (void *ptr, std::size_t count, std::size_t node_size) noexcept
 
bool try_deallocate_array (void *ptr, std::size_t count, std::size_t node_size) noexcept
 
void reserve (std::size_t node_size, std::size_t capacity)
 
std::size_t max_node_size () const noexcept
 
std::size_t pool_capacity_left (std::size_t node_size) const noexcept
 
std::size_t capacity_left () const noexcept
 
std::size_t next_capacity () const noexcept
 
allocator_type & get_allocator () noexcept
 
 memory_pool_collection (memory_pool_collection &&other) noexcept
 
memory_pool_collectionoperator= (memory_pool_collection &&other) noexcept
 

Constructors

◆ memory_pool_collection() [1/2]

memory_pool_collection ( std::size_t  max_node_size,
std::size_t  block_size,
Args &&...  args 
)
Effects:
Creates it by giving it the maximum node size it should be able to allocate, the size of the initial memory block and other constructor arguments for the BlockAllocator. The BucketDistribution controls how many free lists are created, but unlike in memory_pool all free lists are initially empty and the first memory block queued.
Requires:
block_size must be non-zero and max_node_size must be a valid node size and smaller than block_size divided by the number of pools.

◆ ~memory_pool_collection()

~memory_pool_collection ( )
defaultnoexcept
Effects:
Destroys the memory_pool_collection by returning all memory blocks, regardless of properly deallocated back to the BlockAllocator.

◆ memory_pool_collection() [2/2]

memory_pool_collection ( memory_pool_collection< PoolType, BucketDistribution, BlockOrRawAllocator > &&  other)
noexcept
Effects:
Moving a memory_pool_collection object transfers ownership over the free lists, i.e. the moved from pool is completely empty and the new one has all its memory. That means that it is not allowed to call deallocate_node() on a moved-from allocator even when passing it memory that was previously allocated by this object.

Member Functions

◆ operator=()

memory_pool_collection & operator= ( memory_pool_collection< PoolType, BucketDistribution, BlockOrRawAllocator > &&  other)
noexcept
Effects:
Moving a memory_pool_collection object transfers ownership over the free lists, i.e. the moved from pool is completely empty and the new one has all its memory. That means that it is not allowed to call deallocate_node() on a moved-from allocator even when passing it memory that was previously allocated by this object.

◆ allocate_node()

void * allocate_node ( std::size_t  node_size)
Effects:
Allocates a node of given size. It first finds the appropriate free list as defined in the BucketDistribution. If it is empty, it will use an implementation defined amount of memory from the arena and inserts it in it. If the arena is empty too, it will request a new memory block from the BlockAllocator of size next_capacity() and puts part of it onto this free list. Then it removes a node from it.
Returns:
A node of given size suitable aligned, i.e. suitable for any type where sizeof(T) < node_size.
Throws:
Anything thrown by the BlockAllocator if a growth is needed or a bad_node_size exception if the node size is too big.

◆ try_allocate_node()

void * try_allocate_node ( std::size_t  node_size)
noexcept
Effects:
Allocates a node of given size. It is similar to allocate_node() but will return nullptr on any failure, instead of growing the arnea and possibly throwing.
Returns:
A node of given size suitable aligned or nullptr in case of failure.

◆ allocate_array()

void * allocate_array ( std::size_t  count,
std::size_t  node_size 
)
Effects:
Allocates an array of nodes by searching for n continuous nodes on the appropriate free list and removing them. Depending on the PoolType this can be a slow operation or not allowed at all. This can sometimes lead to a growth on the free list, even if technically there is enough continuous memory on the free list. Otherwise has the same behavior as allocate_node().
Returns:
An array of n nodes of size node_size suitable aligned.
Throws:
Anything thrown by the used BlockAllocator's allocation function if a growth is needed, or a bad_allocation_size exception.
Requires:
count must be valid array count and node_size must be valid node size.

◆ try_allocate_array()

void * try_allocate_array ( std::size_t  count,
std::size_t  node_size 
)
noexcept
Effects:
Allocates a array of given size. It is similar to allocate_node() but will return nullptr on any failure, instead of growing the arnea and possibly throwing.
Returns:
A array of given size suitable aligned or nullptr in case of failure.

◆ deallocate_node()

void deallocate_node ( void *  ptr,
std::size_t  node_size 
)
noexcept
Effects:
Deallocates a node by putting it back onto the appropriate free list.
Requires:
ptr must be a result from a previous call to allocate_node() with the same size on the same free list, i.e. either this allocator object or a new object created by moving this to it.

◆ try_deallocate_node()

bool try_deallocate_node ( void *  ptr,
std::size_t  node_size 
)
noexcept
Effects:
Deallocates a node similar to deallocate_node(). But it checks if it can deallocate this memory.
Returns:
true if the node could be deallocated, false otherwise.

◆ deallocate_array()

void deallocate_array ( void *  ptr,
std::size_t  count,
std::size_t  node_size 
)
noexcept
Effects:
Deallocates an array by putting it back onto the free list.
Requires:
ptr must be a result from a previous call to allocate_array() with the same sizes on the same free list, i.e. either this allocator object or a new object created by moving this to it.

◆ try_deallocate_array()

bool try_deallocate_array ( void *  ptr,
std::size_t  count,
std::size_t  node_size 
)
noexcept
Effects:
Deallocates a array similar to deallocate_array(). But it checks if it can deallocate this memory.
Returns:
true if the array could be deallocated, false otherwise.

◆ reserve()

void reserve ( std::size_t  node_size,
std::size_t  capacity 
)
Effects:
Inserts more memory on the free list for nodes of given size. It will try to put capacity_left bytes from the arena onto the free list defined over the BucketDistribution, if the arena is empty, a new memory block is requested from the BlockAllocator and it will be used.
Throws:
Anything thrown by the BlockAllocator if a growth is needed.
Requires:
node_size must be valid node size less than or equal to max_node_size(), capacity_left must be less than next_capacity().

◆ max_node_size()

std::size_t max_node_size ( ) const
noexcept
Returns:
The maximum node size for which is a free list. This is the value passed to it in the constructor.

◆ pool_capacity_left()

std::size_t pool_capacity_left ( std::size_t  node_size) const
noexcept
Returns:
The amount of nodes available in the free list for nodes of given size as defined over the BucketDistribution. This is the number of nodes that can be allocated without the free list requesting more memory from the arena.
Note
Array allocations may lead to a growth even if the capacity_left is big enough.

◆ capacity_left()

std::size_t capacity_left ( ) const
noexcept
Returns:
The amount of memory available in the arena not inside the free lists. This is the number of bytes that can be inserted into the free lists without requesting more memory from the BlockAllocator.
Note
Array allocations may lead to a growth even if the capacity is big enough.

◆ next_capacity()

std::size_t next_capacity ( ) const
noexcept
Returns:
The size of the next memory block after capacity_left() arena grows. This is the amount of memory that can be distributed in the pools.
Note
If the PoolType is small_node_pool, the exact usable memory is lower than that.

◆ get_allocator()

allocator_type & get_allocator ( )
noexcept
Returns:
A reference to the BlockAllocator used for managing the arena.
Requires:
It is undefined behavior to move this allocator out into another object.