memory_pool_collection< PoolType, BucketDistribution, BlockOrRawAllocator > Class Template Reference
Allocator implementations

## 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_collection & | operator= (memory_pool_collection &&other) noexcept

## Constructors

## memory_pool_collection() [1/2]

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>
template<typename... Args>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

~memory_pool_collection | ( |  | ) |

default noexcept

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

## memory_pool_collection() [2/2]

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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=()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_allocator>

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()

template<class PoolType , class BucketDistribution , class BlockOrRawAllocator = default_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.