LibSWOC++ 1.5.14
Solid Wall of C++
Loading...
Searching...
No Matches
swoc::MemArena Class Reference

#include <MemArena.h>

Collaboration diagram for swoc::MemArena:
Collaboration graph

Classes

struct  Block
 Simple internal arena block of memory. Maintains the underlying memory. More...
 

Public Types

using unique_ptr = std::unique_ptr<self_type, void (*)(self_type *)>
 
using BlockList = IntrusiveDList<Block::Linkage>
 Intrusive list of blocks.
 
using const_iterator = BlockList::const_iterator
 Constant element iteration.
 
using iterator = const_iterator
 Element iteration.
 

Public Member Functions

 MemArena (size_t n=DEFAULT_BLOCK_SIZE)
 
 MemArena (MemSpan< void > static_block)
 
 MemArena (self_type const &that)=delete
 no copying
 
 MemArena (self_type &&that) noexcept
 Allow moving the arena.
 
 ~MemArena ()
 Destructor.
 
self_typeoperator= (self_type const &that)=delete
 No copy assignment.
 
self_typeoperator= (self_type &&that) noexcept
 Move assignment.
 
MemSpan< void > alloc (size_t n, size_t align=DEFAULT_ALIGNMENT)
 
template<typename T>
MemSpan< T > alloc_span (size_t n)
 
template<typename T, typename... Args>
T * make (Args &&...args)
 
MemSpan< char > localize (MemSpan< char const > s)
 
MemSpan< char > localize (char const *s)
 
MemSpan< char > localize_c (MemSpan< char const > s)
 
MemSpan< char > localize_c (char const *s)
 
MemArenafreeze (size_t n=0)
 
self_typethaw ()
 
MemArenaclear (size_t hint=0)
 
MemArenadiscard (MemSpan< void const > span)
 
MemArenadiscard (size_t hint=0)
 
size_t size () const
 
size_t remaining () const
 
template<typename T>
MemSpan< T > remnant_span (size_t n)
 
MemSpan< void > remnant ()
 
MemSpan< void > remnant (size_t n, size_t align=DEFAULT_ALIGNMENT)
 
self_typerequire (size_t n, size_t align=DEFAULT_ALIGNMENT)
 
size_t allocated_size () const
 
bool contains (const void *ptr) const
 
size_t reserved_size () const
 
const_iterator begin () const
 First active block.
 
const_iterator end () const
 After Last active block.
 
const_iterator frozen_begin () const
 First frozen block.
 
const_iterator frozen_end () const
 After last frozen block.
 

Static Public Member Functions

static self_typeconstruct_self_contained (size_t n=DEFAULT_BLOCK_SIZE)
 

Static Public Attributes

static constexpr size_t DEFAULT_ALIGNMENT {1}
 Default memory alignment.
 
static void(* destroyer )(self_type *) = std::destroy_at<MemArena>
 

Protected Types

using Page = Scalar<4096>
 Size for rounding block sizes.
 
using QuarterPage = Scalar<Page::SCALE / 4>
 Quarter page - unit for sub page sizes.
 
using Paragraph = Scalar<16>
 Minimum unit of memory allocation.
 

Protected Member Functions

Blockmake_block (size_t n)
 
void destroy_frozen ()
 Clean up the frozen list.
 
void destroy_active ()
 Clean up the active list.
 

Protected Attributes

size_t _active_allocated = 0
 Total allocations in the active generation.
 
size_t _active_reserved = 0
 
size_t _frozen_allocated = 0
 Total allocations in the previous generation. This is only non-zero while the arena is frozen.
 
size_t _frozen_reserved = 0
 Total frozen reserved memory.
 
size_t _reserve_hint = 0
 
BlockList _frozen
 Previous generation, frozen memory.
 
BlockList _active
 Current generation. Allocate here.
 
Block_static_block = nullptr
 Static block, if any.
 

Static Protected Attributes

static constexpr size_t ALLOC_HEADER_SIZE = 16
 
static constexpr size_t DEFAULT_BLOCK_SIZE = Page::SCALE - Paragraph{round_up(ALLOC_HEADER_SIZE + sizeof(Block))}
 Initial block size to allocate if not specified via API.
 

Detailed Description

A memory arena.

The intended use is for allocating many small chunks of memory - few, large allocations are best handled through other mechanisms. The purpose is to amortize the cost of allocation of each chunk across larger internal allocations ("reserving memory"). In addition the allocated memory chunks are presumed to have similar lifetimes so all of the memory in the arena can be released when the arena is destroyed.

Definition at line 33 of file MemArena.h.

Member Typedef Documentation

◆ BlockList

using swoc::MemArena::BlockList = IntrusiveDList<Block::Linkage>

Intrusive list of blocks.

Definition at line 178 of file MemArena.h.

◆ const_iterator

using swoc::MemArena::const_iterator = BlockList::const_iterator

Constant element iteration.

Definition at line 447 of file MemArena.h.

◆ iterator

Element iteration.

Definition at line 448 of file MemArena.h.

◆ Page

using swoc::MemArena::Page = Scalar<4096>
protected

Size for rounding block sizes.

Definition at line 476 of file MemArena.h.

◆ Paragraph

using swoc::MemArena::Paragraph = Scalar<16>
protected

Minimum unit of memory allocation.

Definition at line 478 of file MemArena.h.

◆ QuarterPage

Quarter page - unit for sub page sizes.

Definition at line 477 of file MemArena.h.

◆ unique_ptr

using swoc::MemArena::unique_ptr = std::unique_ptr<self_type, void (*)(self_type *)>

Correct type for a unique pointer to an instance. Initialization is

static void(* destroyer)(self_type *)
Definition MemArena.h:45
std::unique_ptr< self_type, void(*)(self_type *)> unique_ptr
Definition MemArena.h:57

To create the arena on demand

static self_type * construct_self_contained(size_t n=DEFAULT_BLOCK_SIZE)
Definition MemArena.cc:54

If the unique pointer is to be initialized with an arena, it should probably be a direct member isntead.

Definition at line 57 of file MemArena.h.

Constructor & Destructor Documentation

◆ MemArena() [1/3]

swoc::MemArena::MemArena ( size_t n = DEFAULT_BLOCK_SIZE)
explicit

Construct with reservation hint.

No memory is initially reserved, but when memory is needed this will be done so at least n bytes of available memory is reserved.

To pre-reserve call alloc(0), e.g.

MemArena arena(512); // Make sure at least 512 bytes available in first block.
arena.alloc(0); // Force allocation of first block.
MemArena(size_t n=DEFAULT_BLOCK_SIZE)
Parameters
nMinimum number of available bytes in the first internally reserved block.

◆ MemArena() [2/3]

swoc::MemArena::MemArena ( MemSpan< void > static_block)
explicit

Construct using static block.

Parameters
static_blockA block of memory that is non-deletable.

static_block is used as the first block for allocation and is never deleted. This makes it possible to have an instance that allocates from stack memory and only allocates from the heap if the static block becomes full.

Note
There is no default block size because the static block is the initial block. Subsequent allocations are based on that size.

Definition at line 21 of file MemArena.cc.

◆ MemArena() [3/3]

swoc::MemArena::MemArena ( self_type && that)
noexcept

Allow moving the arena.

Definition at line 37 of file MemArena.cc.

◆ ~MemArena()

swoc::MemArena::~MemArena ( )

Destructor.

Definition at line 256 of file MemArena.cc.

Member Function Documentation

◆ alloc()

MemSpan< void > swoc::MemArena::alloc ( size_t n,
size_t align = DEFAULT_ALIGNMENT )

Allocate n bytes of storage.

Returns a span of memory within the arena. alloc() is self expanding but DOES NOT self coalesce. This means that no matter the arena size, the caller will always be able to alloc() n bytes.

Parameters
nnumber of bytes to allocate.
alignRequired alignment, defaults to 1 (no alignment). Must be a power of 2.
Returns
a MemSpan of the allocated memory.

Definition at line 103 of file MemArena.cc.

◆ alloc_span()

template<typename T>
MemSpan< T > swoc::MemArena::alloc_span ( size_t n)

ALlocate a span of memory sufficient for n instance of T.

Template Parameters
TElement type.
Parameters
nNumber of instances.
Returns
A span large enough to hold n instances of T.

The instances are not initialized / constructed. This only allocates the memory. This is handy for types that don't need initialization, such as built in types like int.

auto vec = arena.alloc_span<int>(20); // allocate space for 20 ints

The memory is aligned according to alignof(T).

◆ allocated_size()

size_t swoc::MemArena::allocated_size ( ) const
Returns
the total number of bytes allocated within the arena.

◆ clear()

MemArena & swoc::MemArena::clear ( size_t hint = 0)

Release all memory.

Empties the entire arena and deallocates all underlying memory. The hint for the next reserved block size will be n if n is not zero, otherwise it will be the sum of all allocations when this method was called.

Parameters
hintSize hint for the next internal allocation.
Returns
this
See also
discard

Definition at line 202 of file MemArena.cc.

◆ construct_self_contained()

MemArena * swoc::MemArena::construct_self_contained ( size_t n = DEFAULT_BLOCK_SIZE)
static

Make a self-contained instance.

Parameters
nThe initial memory size hint.
Returns
A new, self contained instance.

Create an instance of MemArena that is stored in its own memory pool. The size hint n is adjusted to account for the space consumed by the MemArena instance. This instance will therefore always have done its initial internal memory allocation to provide space for itself.

This is most useful for smaller objects that need to strongly minimize their size when not allocating memory. In that context, this enables being able to have a memory pool as needed at the cost of a only single pointer in the instance.

Note
This requires careful attention to detail for freezing and thawing, as the MemArena itself will be in the frozen memory and must be moved to the fresh allocation.
delete must not be called on the returned pointer. Instead the MemArena destructor must be explicitly called, which will clean up all of the allocated memory. See the documentation for further details.

Definition at line 54 of file MemArena.cc.

◆ contains()

bool swoc::MemArena::contains ( const void * ptr) const

Check if a the byte at ptr is in memory owned by this arena.

Parameters
ptrAddress of byte to check.
Returns
true if the byte at ptr is in the arena, false if not.

Definition at line 145 of file MemArena.cc.

◆ destroy_active()

void swoc::MemArena::destroy_active ( )
protected

Clean up the active list.

Definition at line 178 of file MemArena.cc.

◆ destroy_frozen()

void swoc::MemArena::destroy_frozen ( )
protected

Clean up the frozen list.

Definition at line 190 of file MemArena.cc.

◆ discard() [1/2]

MemArena & swoc::MemArena::discard ( MemSpan< void const > span)

Best effort allocation discard.

The allocation is discard (become unallocated memory) if and only if it is at the end of a recent allocation block. If nothing has been allocated, this always works. Otherwise if later allocation exists, this method silently fails. This can work with multiple allocations in a stack - if all later allocations are discarded when this method is invoked it will succeed.

Note
This is purely a performance enhancement to enable computing with internally allocated but unused memory. Compare with remnant
No destruction or other clean up is done, the span is simply marked as unallocated.
Parameters
hintSize hint for the next internal allocation.
Returns
this.
See also
remnant

Definition at line 213 of file MemArena.cc.

◆ discard() [2/2]

MemArena & swoc::MemArena::discard ( size_t hint = 0)

Discard all allocations.

All active internal memory blocks are reset to be empty, discarding any allocations. These blocks will be re-used by subsequent allocations.

Parameters
hintSize hint for the next internal allocation.
Returns
this.
See also
clear

Definition at line 243 of file MemArena.cc.

◆ freeze()

MemArena & swoc::MemArena::freeze ( size_t n = 0)

Freeze reserved memory.

All internal memory blocks are frozen and will not be involved in future allocations. Subsequent allocation will reserve new internal blocks. By default the first reserved block will be large enough to contain all frozen memory. If this is not correct a different target can be specified as n.

Parameters
nTarget number of available bytes in the next reserved internal block.
Returns
*this

Definition at line 118 of file MemArena.cc.

◆ localize() [1/2]

MemSpan< char > swoc::MemArena::localize ( char const * s)

Copy the contents of a string view into the arena.

Parameters
sOriginal string.
Returns
A view of the copy of s.

◆ localize() [2/2]

MemSpan< char > swoc::MemArena::localize ( MemSpan< char const > s)

Copy the contents of a string view into the arena.

Parameters
sOriginal string.
Returns
A view of the copy of s.

◆ localize_c() [1/2]

MemSpan< char > swoc::MemArena::localize_c ( char const * s)

Copy the contents of a string view into the arena as a C string.

Parameters
sOriginal string.
Returns
A view of the copy of s.

A terminating nul character is added to the copy which is not included in the returned view. This enables using the string view as a C string.

◆ localize_c() [2/2]

MemSpan< char > swoc::MemArena::localize_c ( MemSpan< char const > s)

Copy the contents of a string view into the arena as a C string.

Parameters
sOriginal string.
Returns
A view of the copy of s.

A terminating nul character is added to the copy which is not included in the returned view. This enables using the string view as a C string.

◆ make()

template<typename T, typename... Args>
T * swoc::MemArena::make ( Args &&... args)

Allocate and initialize a block of memory as an instance of T

The template type specifies the type to create and any arguments are forwarded to the constructor. Example:

struct Thing { ... };
auto thing = arena.make<Thing>(...constructor args...);

Do not call delete an object created this way - that will attempt to free the memory and break. A destructor may be invoked explicitly but the point of this class is that no object in it needs to be deleted, the memory will all be reclaimed when the Arena is destroyed. In general it is a bad idea to make objects in the Arena that own memory that is not also in the Arena.

◆ make_block()

MemArena::Block * swoc::MemArena::make_block ( size_t n)
protected

Internally allocates a new block of memory of size n bytes.

Parameters
nSize of block to allocate.
Returns

Definition at line 73 of file MemArena.cc.

◆ operator=()

MemArena & swoc::MemArena::operator= ( self_type && that)
noexcept

Move assignment.

Definition at line 60 of file MemArena.cc.

◆ remaining()

size_t swoc::MemArena::remaining ( ) const
Returns
The amount of free space.

◆ remnant() [1/2]

MemSpan< void > swoc::MemArena::remnant ( )
Returns
Contiguous free space in the current internal block.

◆ remnant() [2/2]

MemSpan< void > swoc::MemArena::remnant ( size_t n,
size_t align = DEFAULT_ALIGNMENT )

Get an aligned remnant.

Parameters
nRemnant size.
alignMemory alignment (default 1, must be power of 2).
Returns
Space in the remnant with minimal alignment padding.
Note
This will always return a span of n bytes, the remnant will be expanded as needed.

◆ remnant_span()

template<typename T>
MemSpan< T > swoc::MemArena::remnant_span ( size_t n)

Get aligned and sized remnant.

Template Parameters
TElement type.
Parameters
nNumber of instances of T
Returns
A span that is in the remnant, correctly aligned with minimal padding.

This is guaranteed to be the same bytes as if alloc<T> was called. The returned span will always be the specified size, the remnant will be expanded as needed.

◆ require()

MemArena & swoc::MemArena::require ( size_t n,
size_t align = DEFAULT_ALIGNMENT )

Require n bytes of contiguous memory to be available for allocation.

Parameters
nNumber of bytes.
alignAlign requirement (default is 1, no alignment).
Returns
this

This forces the remnant to be at least n bytes of contiguous memory. A subsequent alloc will use this space if the allocation size is at most the remnant size.

Definition at line 152 of file MemArena.cc.

◆ reserved_size()

size_t swoc::MemArena::reserved_size ( ) const

Total memory footprint, including wasted space.

Returns
Total memory footprint.

◆ size()

size_t swoc::MemArena::size ( ) const
Returns
The amount of memory allocated.

◆ thaw()

MemArena & swoc::MemArena::thaw ( )

Unfreeze arena.

Frozen memory is released.

Returns
*this

Definition at line 133 of file MemArena.cc.

Member Data Documentation

◆ _active

BlockList swoc::MemArena::_active
protected

Current generation. Allocate here.

Definition at line 495 of file MemArena.h.

◆ _active_allocated

size_t swoc::MemArena::_active_allocated = 0
protected

Total allocations in the active generation.

Definition at line 484 of file MemArena.h.

◆ _active_reserved

size_t swoc::MemArena::_active_reserved = 0
protected

Total reserved memory (allocated from OS).

Definition at line 485 of file MemArena.h.

◆ _frozen

BlockList swoc::MemArena::_frozen
protected

Previous generation, frozen memory.

Definition at line 494 of file MemArena.h.

◆ _frozen_allocated

size_t swoc::MemArena::_frozen_allocated = 0
protected

Total allocations in the previous generation. This is only non-zero while the arena is frozen.

Definition at line 487 of file MemArena.h.

◆ _frozen_reserved

size_t swoc::MemArena::_frozen_reserved = 0
protected

Total frozen reserved memory.

Definition at line 488 of file MemArena.h.

◆ _reserve_hint

size_t swoc::MemArena::_reserve_hint = 0
protected

Minimum free space needed in the next allocated block. This is not zero iff reserve was called.

Definition at line 492 of file MemArena.h.

◆ _static_block

Block* swoc::MemArena::_static_block = nullptr
protected

Static block, if any.

Definition at line 498 of file MemArena.h.

◆ ALLOC_HEADER_SIZE

size_t swoc::MemArena::ALLOC_HEADER_SIZE = 16
staticconstexprprotected

Guess of overhead of malloc

Definition at line 480 of file MemArena.h.

◆ DEFAULT_ALIGNMENT

size_t swoc::MemArena::DEFAULT_ALIGNMENT {1}
staticconstexpr

Default memory alignment.

Definition at line 41 of file MemArena.h.

◆ DEFAULT_BLOCK_SIZE

size_t swoc::MemArena::DEFAULT_BLOCK_SIZE = Page::SCALE - Paragraph{round_up(ALLOC_HEADER_SIZE + sizeof(Block))}
staticconstexprprotected

Initial block size to allocate if not specified via API.

Definition at line 482 of file MemArena.h.

◆ destroyer

void(* swoc::MemArena::destroyer)(MemArena *) = std::destroy_at<MemArena>
static

Convenient alias for use with unique_ptr.

Definition at line 45 of file MemArena.h.


The documentation for this class was generated from the following files: