![]() |
mutable
A Database System for Research and Fast Prototyping
|
Implements a list allocator. More...
#include <list_allocator.hpp>
Public Types | |
using | base_type = allocator< list_allocator > |
using | size_type = std::size_t |
Public Member Functions | |
list_allocator (size_type initial_size=0, AllocationStrategy strategy=AllocationStrategy::Linear) | |
~list_allocator () | |
list_allocator (const list_allocator &other) | |
Copy c'tor. | |
list_allocator (list_allocator &&other) | |
list_allocator & | operator= (list_allocator other) |
void * | allocate (const size_type size, const size_type alignment=0) |
void | deallocate (void *ptr, const size_type size) |
size_type | num_chunks_available () const |
void | dump (std::ostream &out) const |
void | dump () const |
std::enable_if_t< not std::is_void_v< T >, T * > | allocate () |
Allocate space for a single entity of type T that is aligned according to T s alignment requirement. | |
std::enable_if_t< not std::is_void_v< T >, T * > | allocate (size_type n) |
Allocate space for an array of n entities of type T . | |
std::enable_if_t< not std::is_void_v< T >, void > | deallocate (T *ptr) |
Deallocate the space for an entity of type T at ptr . | |
std::enable_if_t< not std::is_void_v< T >, void > | deallocate (T *arr, size_type n) |
Deallocate the space for an array of n entities of type T . | |
std::enable_if_t< not std::is_array_v< T >, std::unique_ptr< T > > | make_unique () |
std::enable_if_t< std::is_array_v< T >, std::unique_ptr< T > > | make_unique (size_type n) |
void | dispose (std::unique_ptr< T > ptr) |
void | dispose (std::unique_ptr< T > ptr, size_type n) |
Private Types | |
using | chunk_list_type = doubly_linked_list< size_type, list_allocator_proxy > |
| |
using | header_type = chunk_list_type::node_type |
| |
Private Member Functions | |
chunk_list_type::iterator | unlink_chunk (chunk_list_type::iterator it) |
Removes the referenced chunk from the list of available chunks without deallocating its memory. | |
chunk_list_type::iterator | link_chunk (chunk_list_type::iterator pos, void *chunk, size_type masked_size) |
Adds the given chunk to the list of unused chunks by emplacing the list node within the chunk's memory. | |
chunk_list_type::iterator | insert_chunk_sorted (void *chunk, size_type masked_size) |
void | reclaim_chunk (void *chunk, size_type masked_size) |
chunk_list_type::iterator | add_fresh_chunk (const size_type size, const size_type alignment) |
Allocates fresh memory that contains enough space to fit a chunk of size size , that is aligned according to alignment , and that also fits a header. | |
chunk_list_type::iterator | split_unused_chunk (chunk_list_type::iterator it, size_type required_size) |
Splits the given chunk into two chunks. | |
chunk_list_type::iterator | coalesce (chunk_list_type::iterator it) |
Attempt to coalesce the chunk pointed to by it and its successor. | |
void * | proxy_allocate (size_type, size_type) |
void | proxy_deallocate (void *ptr, size_type) |
void * | aligned_mmap (size_type size, size_type alignment) |
Static Private Member Functions | |
static bool | is_unaligned (void *ptr, size_type alignment) |
static bool | is_aligned (void *ptr, size_type alignment) |
static size_type & | size_of_used_chunk (void *chunk, const size_type size) |
Returns a reference to the effective size field of a chunk in use. | |
static size_type | size_of_used_chunk (const void *chunk, const size_type size) |
static header_type * | header_of_unused_chunk (size_type *value_addr) |
Returns a pointer to the header of an unused chunk. | |
static const header_type * | header_of_unused_chunk (const size_type *value_addr) |
static bool | is_marked_for_deallocation (const header_type *header) |
static size_type | extract_size (const header_type *header) |
static size_type | mark_for_deallocation (size_type n) |
static size_type | preserve_deallocation (size_type n, const header_type *header) |
Private Attributes | |
size_type | min_allocation_size_ |
| |
size_type | min_allocation_alignment_ |
| |
AllocationStrategy | strategy_ |
| |
chunk_list_type | chunks_ |
| |
void * | override_addr_ = nullptr |
| |
Static Private Attributes | |
static constexpr size_type | CHUNK_SPLIT_FACTOR = 2 |
| |
static constexpr size_type | DEALLOCATION_BIT_MASK = size_type(1U) << (sizeof(size_type) * CHAR_BIT - 1U) |
| |
Friends | |
struct | list_allocator_proxy |
void | swap (list_allocator &first, list_allocator &second) |
M_LCOV_EXCL_START friend std::ostream & | operator<< (std::ostream &out, const list_allocator &A) |
Implements a list allocator.
Allocated (in use) chunk: +--------—+---—+----------—+ | used part | size | unused part | +--------—+---—+----------—+ ^^^^ header
The unused part may be empty.
Unused (in list) chunk: +--------—+-----------------—+ | ptr, size | unused space | +--------—+-----------------—+ ^^^^^^^^^ header
The crux is to move the header when a chunk is allocated. This enables us to locate the header once the chunk is deallocated. The header stores the effective/actual size of the chunk. (It does not necessarily store the size requested by the client's allocation. As long as a chunk is in use, we have no way of locating the header. The client must properly deallocate the chunk by specifying the size that was specified when the chunk was allocated.
Definition at line 93 of file list_allocator.hpp.
Definition at line 97 of file list_allocator.hpp.
|
private |
the type of the internal list of unused chunks
Definition at line 115 of file list_allocator.hpp.
|
private |
the type of a list node, which is the "header" of an unused chunk
Definition at line 119 of file list_allocator.hpp.
|
inherited |
Definition at line 19 of file allocator_base.hpp.
|
inline |
Definition at line 144 of file list_allocator.hpp.
References add_fresh_chunk(), chunks_, m::doubly_linked_list< T, Allocator >::empty(), m::get_pagesize(), M_insist, min_allocation_alignment_, min_allocation_size_, and m::doubly_linked_list< T, Allocator >::size().
|
inline |
Definition at line 162 of file list_allocator.hpp.
References m::doubly_linked_list< T, Allocator >::begin(), chunks_, m::doubly_linked_list< T, Allocator >::empty(), m::doubly_linked_list< T, Allocator >::erase(), extract_size(), header_of_unused_chunk(), is_marked_for_deallocation(), and override_addr_.
|
inlineexplicit |
Copy c'tor.
Copies the current behavior (allocation size and strategy). Does not copy the current allocations.
Definition at line 177 of file list_allocator.hpp.
|
inline |
Definition at line 181 of file list_allocator.hpp.
References swap.
|
inlineprivate |
Allocates fresh memory that contains enough space to fit a chunk of size size
, that is aligned according to alignment
, and that also fits a header.
The chunk is added to the list of chunks.
Definition at line 351 of file list_allocator.hpp.
References aligned_mmap(), m::Exponential, insert_chunk_sorted(), is_aligned(), m::is_pow_2(), m::Linear, M_insist, mark_for_deallocation(), min_allocation_alignment_, min_allocation_size_, override_addr_, and strategy_.
Referenced by allocate(), and list_allocator().
Definition at line 479 of file list_allocator.hpp.
References m::get_pagesize(), is_aligned(), and M_insist.
Referenced by add_fresh_chunk().
|
inlineinherited |
Allocate space for a single entity of type T
that is aligned according to T
s alignment requirement.
Definition at line 40 of file allocator_base.hpp.
Definition at line 185 of file list_allocator.hpp.
References add_fresh_chunk(), m::and, m::doubly_linked_list< T, Allocator >::begin(), CHUNK_SPLIT_FACTOR, chunks_, m::doubly_linked_list< T, Allocator >::end(), extract_size(), header_of_unused_chunk(), m::is_pow_2(), is_unaligned(), M_insist, size_of_used_chunk(), split_unused_chunk(), and unlink_chunk().
|
inlineinherited |
Allocate space for an array of n
entities of type T
.
The space is aligned according to T
s alignment requirement.
Definition at line 46 of file allocator_base.hpp.
|
inlineprivate |
Attempt to coalesce the chunk pointed to by it
and its successor.
it
otherwise Definition at line 428 of file list_allocator.hpp.
References chunks_, m::doubly_linked_list< T, Allocator >::end(), extract_size(), header_of_unused_chunk(), is_marked_for_deallocation(), M_insist, and unlink_chunk().
Referenced by reclaim_chunk().
|
inlineinherited |
Deallocate the space for an array of n
entities of type T
.
Definition at line 56 of file allocator_base.hpp.
|
inlineinherited |
Deallocate the space for an entity of type T
at ptr
.
Definition at line 51 of file allocator_base.hpp.
|
inline |
Definition at line 230 of file list_allocator.hpp.
References reclaim_chunk(), and size_of_used_chunk().
|
inlineinherited |
Definition at line 71 of file allocator_base.hpp.
|
inlineinherited |
Definition at line 74 of file allocator_base.hpp.
|
inline |
|
inline |
Definition at line 255 of file list_allocator.hpp.
|
inlinestaticprivate |
Definition at line 301 of file list_allocator.hpp.
Referenced by allocate(), coalesce(), split_unused_chunk(), and ~list_allocator().
|
inlinestaticprivate |
Definition at line 294 of file list_allocator.hpp.
|
inlinestaticprivate |
Returns a pointer to the header of an unused chunk.
Definition at line 289 of file list_allocator.hpp.
Referenced by allocate(), coalesce(), reclaim_chunk(), split_unused_chunk(), unlink_chunk(), and ~list_allocator().
|
inlineprivate |
Definition at line 329 of file list_allocator.hpp.
References m::and, m::doubly_linked_list< T, Allocator >::begin(), chunks_, m::doubly_linked_list< T, Allocator >::end(), and link_chunk().
Referenced by add_fresh_chunk(), and reclaim_chunk().
|
inlinestaticprivate |
Definition at line 269 of file list_allocator.hpp.
References is_unaligned().
Referenced by add_fresh_chunk(), and aligned_mmap().
|
inlinestaticprivate |
Definition at line 300 of file list_allocator.hpp.
References DEALLOCATION_BIT_MASK.
Referenced by coalesce(), split_unused_chunk(), and ~list_allocator().
|
inlinestaticprivate |
Definition at line 264 of file list_allocator.hpp.
References m::is_pow_2(), and M_insist.
Referenced by allocate(), and is_aligned().
|
inlineprivate |
Adds the given chunk
to the list of unused chunks by emplacing the list node within the chunk's memory.
The list node is inserted at position pos
within the linked list.
Definition at line 321 of file list_allocator.hpp.
References chunks_, m::doubly_linked_list< T, Allocator >::end(), m::doubly_linked_list< T, Allocator >::insert(), M_insist, and override_addr_.
Referenced by insert_chunk_sorted(), and split_unused_chunk().
|
inlineinherited |
Definition at line 64 of file allocator_base.hpp.
|
inlineinherited |
Definition at line 68 of file allocator_base.hpp.
Definition at line 302 of file list_allocator.hpp.
References DEALLOCATION_BIT_MASK.
Referenced by add_fresh_chunk().
|
inline |
Definition at line 236 of file list_allocator.hpp.
References chunks_, and m::doubly_linked_list< T, Allocator >::size().
|
inline |
Definition at line 183 of file list_allocator.hpp.
References swap.
|
inlinestaticprivate |
Definition at line 303 of file list_allocator.hpp.
References DEALLOCATION_BIT_MASK.
Referenced by split_unused_chunk().
Definition at line 466 of file list_allocator.hpp.
References M_insist, and override_addr_.
|
inlineprivate |
Definition at line 473 of file list_allocator.hpp.
References M_insist, and override_addr_.
|
inlineprivate |
Definition at line 338 of file list_allocator.hpp.
References m::doubly_linked_list< T, Allocator >::begin(), chunks_, coalesce(), m::doubly_linked_list< T, Allocator >::end(), header_of_unused_chunk(), insert_chunk_sorted(), and M_insist.
Referenced by deallocate().
|
inlinestaticprivate |
Definition at line 282 of file list_allocator.hpp.
|
inlinestaticprivate |
Returns a reference to the effective size field of a chunk in use.
Definition at line 277 of file list_allocator.hpp.
Referenced by allocate(), and deallocate().
|
inlineprivate |
Splits the given chunk
into two chunks.
The first chunk will be located at chunk
and have a usable size not less than required_size
. The second chunk, containing the remaining space of the original chunk, is added to the list of chunks. Alignment is assumed and not checked.
Definition at line 391 of file list_allocator.hpp.
References extract_size(), header_of_unused_chunk(), is_marked_for_deallocation(), link_chunk(), M_insist, and preserve_deallocation().
Referenced by allocate().
|
inlineprivate |
Removes the referenced chunk from the list of available chunks without deallocating its memory.
Definition at line 313 of file list_allocator.hpp.
References chunks_, m::doubly_linked_list< T, Allocator >::erase(), header_of_unused_chunk(), and override_addr_.
Referenced by allocate(), and coalesce().
|
friend |
Definition at line 95 of file list_allocator.hpp.
|
friend |
Definition at line 239 of file list_allocator.hpp.
|
friend |
Definition at line 124 of file list_allocator.hpp.
Referenced by list_allocator(), and operator=().
|
staticconstexprprivate |
the factor by which a chunk must be larger than the requested allocation to be considered for splitting
Definition at line 103 of file list_allocator.hpp.
Referenced by allocate().
|
private |
the list of unused (free) chunks
Definition at line 117 of file list_allocator.hpp.
Referenced by allocate(), coalesce(), insert_chunk_sorted(), link_chunk(), list_allocator(), num_chunks_available(), reclaim_chunk(), unlink_chunk(), and ~list_allocator().
|
staticconstexprprivate |
mask of the high bit of a size_type (the type of the header of a used chunk)
Definition at line 105 of file list_allocator.hpp.
Referenced by is_marked_for_deallocation(), mark_for_deallocation(), and preserve_deallocation().
|
private |
the minimum alignment of an actual memory allocation
Definition at line 110 of file list_allocator.hpp.
Referenced by add_fresh_chunk(), and list_allocator().
|
private |
the size of the next actual memory allocation
Definition at line 108 of file list_allocator.hpp.
Referenced by add_fresh_chunk(), and list_allocator().
|
private |
used to override the behavior of allocation requests by
chunks_
by routing through a proxy allocator
Definition at line 121 of file list_allocator.hpp.
Referenced by add_fresh_chunk(), link_chunk(), proxy_allocate(), proxy_deallocate(), unlink_chunk(), and ~list_allocator().
|
private |
the allocation strategy; influences how
min_allocation_size_
is updated with each actual allocation
Definition at line 112 of file list_allocator.hpp.
Referenced by add_fresh_chunk().