density
C++11 library for paged memory management, function queues, heterogeneous queues and lifo memory management
Public Types | Public Member Functions | Static Public Attributes | List of all members
lifo_allocator< UNDERLYING_ALLOCATOR, ALIGNMENT > Class Template Reference

#include <lifo.h>

Public Types

using underlying_allocator = UNDERLYING_ALLOCATOR
 

Public Member Functions

constexpr lifo_allocator () noexcept
 
 lifo_allocator (const UNDERLYING_ALLOCATOR &i_underlying_allocator)
 
 lifo_allocator (UNDERLYING_ALLOCATOR &&i_underlying_allocator)
 
 lifo_allocator (const lifo_allocator &)=delete
 
lifo_allocatoroperator= (const lifo_allocator &)=delete
 
void * allocate (size_t i_size)
 
void * allocate_empty () noexcept
 
void deallocate (void *i_block, size_t i_size) noexcept
 
void * reallocate (void *i_block, size_t i_old_size, size_t i_new_size)
 
 ~lifo_allocator ()
 
UNDERLYING_ALLOCATOR & underlying_allocator_ref () noexcept
 
const UNDERLYING_ALLOCATOR & underlying_allocator_ref () const noexcept
 

Static Public Attributes

static constexpr size_t alignment = ALIGNMENT
 

Detailed Description

template<typename UNDERLYING_ALLOCATOR = default_allocator, size_t ALIGNMENT = alignof(void *)>
class density::lifo_allocator< UNDERLYING_ALLOCATOR, ALIGNMENT >

Class template that provides LIFO memory management.

Template Parameters
UNDERLYING_ALLOCATORUnderlying allocator class, that can be stateless or stateful. It must meet the requirements of both UntypedAllocator and PagedAllocator.
ALIGNMENTAlignment of the blocks. It must be non-zero and a power of 2.

A lifo_allocator uses memory pages allocated from the underlying allocator to provide lifo memory management to the user. It is designed to be efficient, so it does not provide an high-level service. All blocks has the same alignment (specified by the template argument), and the size of the requested blocks must be a multiple of it. Deallocation and reallocation functions require the caller to specify the current size of the block. Blocks that are very large according to a some implementation-defined criteria, are handled with legacy heap allocations.

A living block is a block allocated, eventually reallocated, but not yet deallocated. Reallocating or deallocating a block which is not the most recently allocated living block causes undefined behavior. Instances of lifo_allocator are not interchangeable: blocks allocated by an instance can't be deallocated with another instance. All living blocks must be deallocated before the allocator is destroyed, otherwise the behavior is undefined.

lifo_allocator is a stateful class template (it has non-static data members). It is uncopyable, unmovable and incomparable.

The constructor of lifo_allocator is constexpr and guarantees constant initialization.

Implementation notes

A block allocation or deallocation requires only a few ALU instructions and a branch to a slow path, that is taken whenever a page switch occurs. The internal state of the allocator is composed by a pointer, that points to the next block allocate would return. A call to allocate_empty just return the top of the stack, without altering the state of the allocator. lifo_allocator does not cache free pages: when a page or a block is no more used, it is immediately deallocated.

Member Typedef Documentation

using underlying_allocator = UNDERLYING_ALLOCATOR

Alias for the template argument UNDERLYING_ALLOCATOR

Constructor & Destructor Documentation

constexpr lifo_allocator ( )
inlinenoexcept

Default constructor, non-throwing and suitable for constant initialization.

lifo_allocator ( const UNDERLYING_ALLOCATOR &  i_underlying_allocator)
inline

Constructs passing the underlying allocator as l-value

lifo_allocator ( UNDERLYING_ALLOCATOR &&  i_underlying_allocator)
inline

Constructs passing the underlying allocator as r-value

lifo_allocator ( const lifo_allocator< UNDERLYING_ALLOCATOR, ALIGNMENT > &  )
delete

Copy construction not allowed

~lifo_allocator ( )
inline

Destroys the allocator, deallocating the bottom page in case this allocator is not virgin

Member Function Documentation

lifo_allocator& operator= ( const lifo_allocator< UNDERLYING_ALLOCATOR, ALIGNMENT > &  )
delete

Copy assignment not allowed

void* allocate ( size_t  i_size)
inline

Allocates a memory block. The content of the newly allocated memory is undefined. The new memory block is aligned at least to alignment.

Parameters
i_sizeThe size of the requested block, in bytes.
Returns
address of the allocated block
Precondition
The behavior is undefined if either:


Throws: unspecified.
Exception guarantee: strong (in case of exception the function has no observable effects).

void* allocate_empty ( )
inlinenoexcept

Allocates a block with size 0.

This function is equivalent to allocate(0), but it is much faster and never throws. The returned block can be reallocated and deallocated.

This function is useful to initialize block owners to an empty state in a noexcept context, without introducing the nullptr special case. The implementation of the default constructor of lifo_buffer uses this function.

Throws: nothing.

Implementation notes: this function just returns the top of the stack, without altering the state of the allocator.

lifo_allocator<> allocator;
constexpr auto alignment = decltype(allocator)::alignment;
auto block = allocator.allocate_empty();
assert(address_is_aligned(block, alignment));
block = allocator.reallocate(block, 0, alignment * 2);
assert(address_is_aligned(block, alignment));
allocator.deallocate(block, alignment * 2);
void deallocate ( void *  i_block,
size_t  i_size 
)
inlinenoexcept

Deallocates the most recently allocated living memory block.

Parameters
i_blockThe memory block to deallocate
i_sizeSize of the block.
Precondition
The behavior is undefined if either:
  • the specified block is null or it is not the most recently allocated
  • the specified size is not the one asked to the most recent reallocation of the block, or to the allocation (If no reallocation was performed)


Throws: nothing.

void* reallocate ( void *  i_block,
size_t  i_old_size,
size_t  i_new_size 
)
inline

Reallocates the most recently allocated living memory block, changing its size. The address of the block may change. The content of the memory block is preserved up to the existing extend. If the memory block is moved to another address, its content is copied with memcopy.

Parameters
i_blockblock to be resized. After the call, if no exception is thrown, this pointer must be discarded, because it may point to invalid memory.
i_old_sizethe previous size of the block, in bytes.
i_new_sizethe new size requested for the block, in bytes.
Returns
the new address of the resized block.
Precondition
The behavior is undefined if either:
  • the specified block is null or it is not the most recently allocated
  • i_old_size is not the one asked to the most recent reallocation of the block, or to the allocation (if no reallocation was performed)
  • i_new_size is not a multiple of alignment


Throws: unspecified.
Exception guarantee: strong (in case of exception the function has no observable effects).

UNDERLYING_ALLOCATOR& underlying_allocator_ref ( )
inlinenoexcept

Returns a reference to the underlying allocator

const UNDERLYING_ALLOCATOR& underlying_allocator_ref ( ) const
inlinenoexcept

Returns a const reference to the underlying allocator

Member Data Documentation

constexpr size_t alignment = ALIGNMENT
static

Alias for the template argument ALIGNMENT


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