auto_buffer Class Template Reference
[Memory Library]

#include <stlsoft/memory/auto_buffer.hpp>

Inheritance diagram for auto_buffer:

stl_collection_tag collection_tag multibyte2wide

List of all members.


Detailed Description

template<typename T, size_t SPACE = auto_buffer_internal_size_calculator<T>::value, typename A = typename allocator_selector<T>::allocator_type>
class stlsoft::auto_buffer< T, SPACE, A >

This class provides an efficient variable automatic buffer.

Parameters:
T The type of the elements in the array
SPACE The number of elements in the array. For translators that support default template arguments, this is defaulted to 256
A The allocator type. Defaults to allocator_selector<T>::allocator_type for translators that support default template arguments.
This class provides an efficient replacement for dynamic memory block allocation when the block size generally falls under a predictable limit. In such cases, significant performance benefits can be achieved by using an instance of a parameterisation of auto_buffer, whose size parameter SPACE is set to a level to cater for most of the requested sizes. Only where the size of the buffer needs to be larger than this limit does an allocation occur from the heap/free-store via the given allocator.

Using auto_buffer means one can avoid use of heap memory in circumstances where stack memory is unsuitable, i.e. where there is no maximum size to a memory requirement, or the maximum size is potentially very large (and considerably larger than the median size). Consider the following code extract from the core of the Pantheios logging library:

  int pantheios_log_n(  pan_sev_t           severity
                     ,  size_t              numSlices
                     ,  pan_slice_t const*  slices)
  {
    typedef stlsoft::auto_buffer<char, 2048>  buffer_t;

    // Calculate the total size of the log statement, by summation of the slice array
    const size_t  n = std::accumulate(stlsoft::member_selector(slices, &pan_slice_t::len)
                                    , stlsoft::member_selector(slices + numSlices, &pan_slice_t::len)
                                    , size_t(0));
    buffer_t      buffer(1 + n);

    . . .

This use of auto_buffer illustrates two important features:

Without auto_buffer, we would have three choices, all bad:

1. We could go to the heap in all cases:

  int pantheios_log_n(  pan_sev_t           severity
                     ,  size_t              numSlices
                     ,  pan_slice_t const*  slices)
  {
    typedef stlsoft::vector<char>   buffer_t;

    // Calculate the total size of the log statement, by summation of the slice array
    const size_t  n = std::accumulate(stlsoft::member_selector(slices, &pan_slice_t::len)
                                    , stlsoft::member_selector(slices + numSlices, &pan_slice_t::len)
                                    , size_t(0));
    buffer_t      buffer(1 + n);

    . . .
But this would have an unacceptable performance hit (since the vast majority of log statements are less than 2K in extent).

2. We could use a stack buffer, and truncate any log statement exceeding the limit:

  int pantheios_log_n(  pan_sev_t           severity
                     ,  size_t              numSlices
                     ,  pan_slice_t const*  slices)
  {
    // Calculate the total size of the log statement, by summation of the slice array
    const size_t  n = std::accumulate(stlsoft::member_selector(slices, &pan_slice_t::len)
                                    , stlsoft::member_selector(slices + numSlices, &pan_slice_t::len)
                                    , size_t(0));
    char          buffer[2048];

    . . . // make sure to truncate the statement to a max 2047 characters
But this would unnecessarily constrain users of the Pantheios logging functionality.

3. Finally, we could synthesise the functionality of auto_buffer manually, as in:

  int pantheios_log_n(  pan_sev_t           severity
                     ,  size_t              numSlices
                     ,  pan_slice_t const*  slices)
  {
    // Calculate the total size of the log statement, by summation of the slice array
    const size_t  n = std::accumulate(stlsoft::member_selector(slices, &pan_slice_t::len)
                                    , stlsoft::member_selector(slices + numSlices, &pan_slice_t::len)
                                    , size_t(0));
    char    buff[2048];
    char    *buffer = (n < 2048) ? &buff[0] : new char[1 + n];

    . . .

    if(buffer != &buff[0])
    {
      delete [] buffer;
    }
But this is onerous manual fiddling, and exception-unsafe. What would be the point, when auto_buffer already does this (safely) for us?

As a consequence of its blending of the best features of stack and heap memory, auto_buffer is an invaluable component in the implementation of many components within the STLSoft libraries, and in several other open-source projects, including: b64, Open-RJ, Pantheios, recls, and shwild.

Remarks:
auto_buffer works correctly whether the given allocator throws an exception on allocation failure, or returns NULL. In the latter case, construction failure to allocate is reflected by the size() method returning 0.

The design of auto_buffer is described in Chapter 32 of Imperfect C++, and its interface is discussed in detail in Section 16.2 of Extended STL, volume 1.

Note:
With version 1.9 of STLSoft, the order of the space and allocator arguments were reversed. Further, the allocator default changed from stlsoft::new_allocator to std::allocator for translators that support the standard library. If you need the old characteristics, you can #define the symbol STLSOFT_AUTO_BUFFER_USE_PRE_1_9_CHARACTERISTICS.
Examples:

by_library/memory/auto_buffer/auto_buffer.cpp, and by_library/windows_registry/registry_functions/registry_functions.cpp.


Implementation

static void block_copy (pointer dest, const_pointer src, size_type cItems)
static void block_set (pointer dest, size_type cItems, const_reference value)

Operations

bool resize (size_type cItems)
 Expands or contracts the number of items in the buffer.
void swap (class_type &rhs) throw ()
 Swaps contents with the given buffer.

Attributes

size_type size () const
 Returns the number of elements in the auto_buffer.
bool empty () const
 Indicates whether the buffer has any contents.
allocator_type get_allocator () const
 Returns an instance of the allocator used to specialise the instance.
static size_type internal_size ()
 Returns the number of elements in the auto_buffer's internal buffer.

Public Types

Member Types
enum  { space = int(SPACE) }
typedef T value_type
 The value type.
typedef A allocator_type
 The allocator type.
typedef auto_buffer< T, space, A > class_type
 The type of the current parameterisation.
typedef allocator_type::reference reference
 The reference type.
typedef
allocator_type::const_reference 
const_reference
 The non-mutable (const) reference type.
typedef allocator_type::pointer pointer
 The pointer type.
typedef
allocator_type::const_pointer 
const_pointer
 The non-mutable (const) pointer type.
typedef size_t size_type
 The size type.
typedef ss_ptrdiff_t difference_type
 The difference type.
typedef value_typeiterator
 The iterator type.
typedef value_type const * const_iterator
 The non-mutable (const) iterator type.

Public Member Functions

Construction
 auto_buffer (size_type cItems)
 Constructs an auto_buffer with the given number of elements.
 ~auto_buffer ()
 Releases the allocated element array.
Operators
reference operator[] (size_type index)
 Subscript operator.
const_reference operator[] (size_type index) const
 Subscript operator.
Accessors
pointer data ()
 Returns a pointer to the element array.
const_pointer data () const
 Returns a pointer-to-const to the element array.
reference front ()
 Returns a reference to the last element in the buffer.
reference back ()
 Returns a reference to the last element in the buffer.
const_reference front () const
 Returns a non-mutating (const) reference to the last element in the buffer.
const_reference back () const
 Returns a non-mutating (const) reference to the last element in the buffer.
Iteration
const_iterator begin () const
 Returns a non-mutating iterator representing the start of the sequence.
const_iterator end () const
 Returns a non-mutating iterator representing the end of the sequence.
iterator begin ()
 Returns a mutable iterator representing the start of the sequence.
iterator end ()
 Returns a mutable iterator representing the end of the sequence.

Member Typedef Documentation

typedef T value_type

The value type.

typedef A allocator_type

The allocator type.

typedef auto_buffer<T, space, A> class_type

The type of the current parameterisation.

typedef allocator_type::reference reference

The reference type.

typedef allocator_type::const_reference const_reference

The non-mutable (const) reference type.

typedef allocator_type::pointer pointer

The pointer type.

Reimplemented in multibyte2wide, and wide2multibyte.

typedef allocator_type::const_pointer const_pointer

The non-mutable (const) pointer type.

typedef size_t size_type

The size type.

Reimplemented in multibyte2wide, and wide2multibyte.

The difference type.

typedef value_type* iterator

The iterator type.

typedef value_type const* const_iterator

The non-mutable (const) iterator type.


Member Enumeration Documentation

anonymous enum

Enumerator:
space  The number of items in the internal buffer.


Constructor & Destructor Documentation

auto_buffer ( size_type  cItems  )  [inline, explicit]

Constructs an auto_buffer with the given number of elements.

Constructs an auto_buffer with the given number of elements. If the allocation fails by throwing an exception, that exception is passed through to the caller. If allocation fails by returning a null pointer the auto_buffer instance is correctly constructed, and the size() method returns 0.

See also:
size()
Parameters:
cItems The number of items in the constructed instance

~auto_buffer (  )  [inline]

Releases the allocated element array.

Releases any allocated memory. If the internal memory buffer was used, then nothing is done, otherwise the allocated memory is returned to the allocator.


Member Function Documentation

bool resize ( size_type  cItems  )  [inline]

Expands or contracts the number of items in the buffer.

Parameters:
cItems The number of items to change in the buffer. If 0, the external array (if allocated) will be deallocated.
Returns:
Returns true if successful. Function failure occurs when sufficient storage for the requested items cannot be allocated. In that case, std::bad_alloc will be throw for allocators that support it, otherwise the function will return false. In either case, the original storage and contents of the buffer will remain unchanged.
Note:
When reducing the number of elements, the implementation favours speed above memory consumption. If the new item size is still larger than the internal storage size (internal_size()) then the heap allocated block will not be changed (i.e. it will not be exchanged for a smaller block).

As from STLSoft version 1.9, the external array is not discarded in favour of the internal array when 0 < cItems < internal_size(). Only resize(0) will deallocate the external array.

void swap ( class_type rhs  )  throw () [inline]

Swaps contents with the given buffer.

Note:
This method is only constant time when the memory for two buffers has been acquired via the allocator. Otherwise, it will depend on the costs of exchanging the memory

Exception-safety: Provides the no-throw guarantee

reference operator[] ( size_type  index  )  [inline]

Subscript operator.

const_reference operator[] ( size_type  index  )  const [inline]

Subscript operator.

pointer data (  )  [inline]

Returns a pointer to the element array.

const_pointer data (  )  const [inline]

Returns a pointer-to-const to the element array.

reference front (  )  [inline]

Returns a reference to the last element in the buffer.

Precondition:
The buffer instance must not be empty

reference back (  )  [inline]

Returns a reference to the last element in the buffer.

Precondition:
The buffer instance must not be empty

const_reference front (  )  const [inline]

Returns a non-mutating (const) reference to the last element in the buffer.

Precondition:
The buffer instance must not be empty

const_reference back (  )  const [inline]

Returns a non-mutating (const) reference to the last element in the buffer.

Precondition:
The buffer instance must not be empty

const_iterator begin (  )  const [inline]

Returns a non-mutating iterator representing the start of the sequence.

Referenced by basic_commandline_parser::basic_commandline_parser(), and basic_commandline_parser::begin().

const_iterator end (  )  const [inline]

Returns a non-mutating iterator representing the end of the sequence.

Note:
In the case where memory allocation has failed in the context where exceptions are not thrown for allocation failure, this method will return the same value as begin(). Hence, operations on the empty auto_buffer<> instance will be safe if made in respect of the range defined by [begin(), end()).

Referenced by basic_commandline_parser::basic_commandline_parser(), basic_commandline_parser::end(), and stlsoft::translate_thousands().

iterator begin (  )  [inline]

Returns a mutable iterator representing the start of the sequence.

iterator end (  )  [inline]

Returns a mutable iterator representing the end of the sequence.

Note:
In the case where memory allocation has failed in the context where exceptions are not thrown for allocation failure, this method will return the same value as begin(). Hence, operations on the empty auto_buffer<> instance will be safe if made in respect of the range defined by [begin(), end()).

size_type size (  )  const [inline]

Returns the number of elements in the auto_buffer.

Note:
In the case where memory allocation has failed in the context where exceptions are not thrown for allocation failure in the constructor, this method will return 0. Hence, operations on the empty auto_buffer<> instance will be safe if made in respect of the value returned by this method.

Referenced by basic_commandline_parser::basic_commandline_parser(), and basic_commandline_parser::size().

static size_type internal_size (  )  [inline, static]

Returns the number of elements in the auto_buffer's internal buffer.

bool empty (  )  const [inline]

Indicates whether the buffer has any contents.

Note:
This will only ever be true when an allocation above the number of elements in the internal array has been requested, and failed.

allocator_type get_allocator (  )  const [inline]

Returns an instance of the allocator used to specialise the instance.


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

Generated on Thu Jun 10 08:58:53 2010 for STLSoft by  doxygen 1.5.6