memory
Typedefs | Static Functions | Member Functions
memory_stack< BlockOrRawAllocator > Class Template Reference

Detailed Description

template<class BlockOrRawAllocator = default_allocator>
class foonathan::memory::memory_stack< BlockOrRawAllocator >

A stateful RawAllocator that provides stack-like (LIFO) allocations.

It uses a memory_arena with a given BlockOrRawAllocator defaulting to growing_block_allocator to allocate huge blocks and saves a marker to the current top. Allocation simply moves this marker by the appropriate number of bytes and returns the pointer at the old marker position, deallocation is not directly supported, only setting the marker to a previously queried position.

Typedefs

using allocator_type = make_block_allocator_t< BlockOrRawAllocator >
 
using marker = implementation_defined
 The marker type that is used for unwinding.
 

Static Functions

static constexpr std::size_t min_block_size (std::size_t byte_size) noexcept
 

Member Functions

template<typename... Args>
 memory_stack (std::size_t block_size, Args &&... args)
 
void * allocate (std::size_t size, std::size_t alignment)
 
void * try_allocate (std::size_t size, std::size_t alignment) noexcept
 
marker top () const noexcept
 
void unwind (marker m) noexcept
 
void shrink_to_fit () noexcept
 
std::size_t capacity_left () const noexcept
 
std::size_t next_capacity () const noexcept
 
allocator_type & get_allocator () noexcept
 

Typedefs

◆ marker

using marker = implementation_defined

The marker type that is used for unwinding.

The exact type is implementation defined, it is only required that it is efficiently copyable and has all the comparision operators defined for two markers on the same stack. Two markers are equal, if they are copies or created from two top() calls without a call to unwind() or allocate(). A marker a is less than marker b, if after a was obtained, there was one or more call to allocate() and no call to unwind().

Constructors

◆ memory_stack()

memory_stack ( std::size_t  block_size,
Args &&...  args 
)
explicit
Effects:
Creates it with a given initial block size and and other constructor arguments for the BlockAllocator. It will allocate the first block and sets the top to its beginning.
Requires:
block_size must be at least min_block_size(1).

Member Functions

◆ min_block_size()

static constexpr std::size_t min_block_size ( std::size_t  byte_size)
staticconstexprnoexcept
Returns:
The minimum block size required for a stack containing the given amount of memory. If a stack is created with the result of min_block_size(n), the resulting capacity will be exactly n.
Requires:
byte_size must be a positive number.
Note
Due to debug fence sizes, the actual amount of usable memory can vary. However, this is impossible to compute without knowing the exact allocation pattern before, so this is just a rough estimate.

◆ allocate()

void * allocate ( std::size_t  size,
std::size_t  alignment 
)
Effects:
Allocates a memory block of given size and alignment. It simply moves the top marker. If there is not enough space on the current memory block, a new one will be allocated by the BlockAllocator or taken from a cache and used for the allocation.
Returns:
A node with given size and alignment.
Throws:
Anything thrown by the BlockAllocator on growth or bad_allocation_size if size is too big.
Requires:
size and alignment must be valid.

◆ try_allocate()

void * try_allocate ( std::size_t  size,
std::size_t  alignment 
)
noexcept
Effects:
Allocates a memory block of given size and alignment, similar to allocate(). But it does not attempt a growth if the arena is empty.
Returns:
A node with given size and alignment or nullptr if there wasn't enough memory available.

◆ top()

marker top ( ) const
noexcept
Returns:
A marker to the current top of the stack.

◆ unwind()

void unwind ( marker  m)
noexcept
Effects:
Unwinds the stack to a certain marker position. This sets the top pointer of the stack to the position described by the marker and has the effect of deallocating all memory allocated since the marker was obtained. If any memory blocks are unused after the operation, they are not deallocated but put in a cache for later use, call shrink_to_fit() to actually deallocate them.
Requires:
The marker must point to memory that is still in use and was the whole time, i.e. it must have been pointed below the top at all time.

◆ shrink_to_fit()

void shrink_to_fit ( )
noexcept
Effects:
unwind() does not actually do any deallocation of blocks on the BlockAllocator, unused memory is stored in a cache for later reuse. This function clears that cache.

◆ capacity_left()

std::size_t capacity_left ( ) const
noexcept
Returns:
The amount of memory remaining in the current block. This is the number of bytes that are available for allocation before the cache or BlockAllocator needs to be used.

◆ next_capacity()

std::size_t next_capacity ( ) const
noexcept
Returns:
The size of the next memory block after the current block is exhausted and the arena grows. This function just forwards to the memory_arena.
Note
All of it is available for the stack to use, but due to fences and alignment buffers, this may not be the exact amount of memory usable for the user.

◆ 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.