density
C++11 library for paged memory management, function queues, heterogeneous queues and lifo memory management
Public Member Functions | Static Public Attributes | List of all members
lifo_buffer Class Reference

#include <lifo.h>

Public Member Functions

 lifo_buffer () noexcept
 
 lifo_buffer (size_t i_size)
 
 lifo_buffer (const lifo_buffer &)=delete
 
lifo_bufferoperator= (const lifo_buffer &)=delete
 
 ~lifo_buffer ()
 
void * resize (size_t i_new_size)
 
void * data () const noexcept
 
size_t size () const noexcept
 

Static Public Attributes

static constexpr size_t alignment = detail::ThreadLifoAllocator<>::alignment
 

Detailed Description

Class that allocates a memory block from the thread-local data stack, and owns it. The block is deallocated by the destructor. This class should be used only on the automatic storage.

The data stack is a pool in which a thread can allocate and deallocate memory in LIFO order. It is handled by an internal lifo_allocator, which in turn in built upon an instance of default_allocator. lifo_array and lifo_buffer allocate on the data stack, so they must respect the LIFO order: only the most recently allocated block can be deallocated or reallocated. Instantiating lifo_array and lifo_buffer on the automatic storage (locally in a function) is always safe, as the language guarantees destruction in reverse order, even inside arrays or aggregate types.

lifo_buffer provides a low-level service, as it allocates untyped raw memory. It allows resizing preserving the content, but it does so memcpy'ng the content when the address of the block changes.

A thread may resize a lifo_buffer only if it is the most recently instantiated lifo_buffer or lifo_array, otherwise the behavior is undefined.

// concatenate and print a null terminated array of strings
void concat_and_print(const char ** i_strings)
{
using namespace density;
while (*i_strings != nullptr)
{
auto const curr_len =
buff.size() > 0 ? buff.size() - 1 : 0; // discard the previous null char, if any
auto const additional_len = strlen(*i_strings);
buff.resize(curr_len + additional_len + 1);
memcpy(static_cast<char *>(buff.data()) + curr_len, *i_strings, additional_len + 1);
i_strings++;
}
std::cout << static_cast<char *>(buff.data()) << std::endl;
}

Constructor & Destructor Documentation

lifo_buffer ( )
inlinenoexcept

Allocates an empty block.

lifo_buffer ( size_t  i_size)
inline

Allocates the block

Parameters
i_sizesize in bytes of the memory block.
lifo_buffer ( const lifo_buffer )
delete

Copy construction not allowed

~lifo_buffer ( )
inline

Deallocates the block

Member Function Documentation

lifo_buffer& operator= ( const lifo_buffer )
delete

Copy assignment not allowed

void* resize ( size_t  i_new_size)
inline

Changes the size of the block, preserving its existing content. If the buffer grows (the new size is bigger than the previous one) the new content has undefined content.

Parameters
i_new_sizesize in bytes of the memory block.
Returns
the new address of the block

This function may reallocate the block, so its address may change.

Precondition
The behavior is undefined if either:
  • this block was not the most recently allocated one on the data stack of the calling thread


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

void* data ( ) const
inlinenoexcept

Returns the address of the owned memory block. If the block is empty (that is the size is zero), the return value is undefined (may be nullptr, or any address), but it's still aligned to alignment.

size_t size ( ) const
inlinenoexcept

Returns the size of the owned memory block.

Member Data Documentation

constexpr size_t alignment = detail::ThreadLifoAllocator<>::alignment
static

Alignment guaranteed for the block


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