|
| Managed_buffer_sequence (const Grow_calculator_t &grow_calculator=Grow_calculator_t(), const Memory_resource_t &memory_resource=Memory_resource_t(), const Size_t default_buffer_count=16) |
| Construct a new, empty object. More...
|
|
| Managed_buffer_sequence (Managed_buffer_sequence &)=delete |
|
| Managed_buffer_sequence (Managed_buffer_sequence &&)=delete |
|
Managed_buffer_sequence & | operator= (Managed_buffer_sequence &)=delete |
|
Managed_buffer_sequence & | operator= (Managed_buffer_sequence &&)=delete |
|
| ~Managed_buffer_sequence () override |
|
Grow_status | reserve_write_size (Size_t requested_write_size) |
| Ensure the write part has at least the given size. More...
|
|
Grow_status | reserve_total_size (Size_t requested_total_size) |
| Ensure the total capacity - the sum of sizes of read part and write part - is at least the given number. More...
|
|
void | reset (Size_t keep_buffer_count=1, Size_t keep_container_capacity=16) |
| Reset the read part and the write part to size 0. More...
|
|
const Grow_calculator_t & | get_grow_calculator () const |
| Return a const reference to the grow calculator. More...
|
|
void | set_grow_calculator (const Grow_calculator_t &grow_calculator) |
| Set the grow calculator. More...
|
|
Grow_status | write (const Char_t *data, Size_t size) |
| Append the given data. More...
|
|
std::string | debug_string (bool show_contents, int indent) const override |
| In debug mode, return a string that describes the internal structure of this object, to use for debugging. More...
|
|
std::string | debug_string (bool show_contents=false) const |
| In debug mode, return a string that describes the internal structure of this object, to use for debugging. More...
|
|
| Rw_buffer_sequence (Iterator_t begin_arg, Iterator_t end_arg) |
| Construct a new Rw_buffer_sequence from given endpoint iterators, with position 0. More...
|
|
| Rw_buffer_sequence (Rw_buffer_sequence &)=delete |
|
| Rw_buffer_sequence (Rw_buffer_sequence &&)=delete |
|
Rw_buffer_sequence & | operator= (Rw_buffer_sequence &)=delete |
|
Rw_buffer_sequence & | operator= (Rw_buffer_sequence &&)=delete |
|
virtual | ~Rw_buffer_sequence ()=default |
|
void | set_position (Size_t new_position) |
| Set the specified absolute position. More...
|
|
void | increase_position (Size_t delta) |
| Move the position right, relative to the current position. More...
|
|
void | move_position (Difference_t delta) |
| Move the position left or right, relative to the current position. More...
|
|
Size_t | capacity () const |
| Return the current size, i.e., total size of all buffers. More...
|
|
const Buffer_sequence_view_t & | read_part () const |
| Return a const reference to the read part. More...
|
|
Buffer_sequence_view_t & | read_part () |
| Return a non-const reference to the read part. More...
|
|
const Buffer_sequence_view_t & | write_part () const |
| Return a const reference to the write part. More...
|
|
Buffer_sequence_view_t & | write_part () |
| Return a non-const reference to the write part. More...
|
|
std::string | debug_string (bool show_contents=false) const |
| In debug mode, return a string that describes the internal structure of this object, to use for debugging. More...
|
|
|
static void | reset_container (Vector_t &container, Size_t keep_container_capacity) |
| std::vector -specific function to reset the container. More...
|
|
static void | reset_container (List_t &container, Size_t keep_container_capacity) |
| std::list -specific function to reset the container. More...
|
|
static void | set_position (Size_t new_position, Buffer_sequence_view_t &left, Buffer_sequence_view_t &right) |
| Move the position to the given, absolute position. More...
|
|
static Size_t | merge_if_split (Buffer_sequence_view_t &left, Buffer_sequence_view_t &right) |
| If a buffer is split between the read and write parts, glue the pieces together again and include them in the read part. More...
|
|
static Size_t | move_position_one_buffer_left (Buffer_sequence_view_t &left, Buffer_sequence_view_t &right) |
| Move the position exactly one buffer left, assuming no buffer is split. More...
|
|
static Size_t | move_position_at_most_one_buffer_right (Buffer_sequence_view_t &left, Buffer_sequence_view_t &right, Size_t limit) |
| Move the position right by whatever is smaller: the given number, or one buffer; splits the buffer if the number is smaller than the buffer. More...
|
|
static std::tuple< Iterator_t, Iterator_t, Size_t > | get_boundaries (Buffer_sequence_view_t &buffer_sequence_view) |
| Return the beginning, end, and size of the read and write parts. More...
|
|
template<class Char_tp = unsigned char, template< class Element_tp, class Allocator_tp > class Container_tp = std::vector>
class mysqlns::buffer::Managed_buffer_sequence< Char_tp, Container_tp >
Owned, non-contiguous, growable memory buffer.
This class never moves buffer data, but is non-contiguous. It is implemented as a container of Buffer objects.
Objects have a growable size, a movable position, and two buffer_sequence_view objects called the read part and the write part, which are accessible through the member functions read_part
and write_part
. The read part is everything preceding the position, and the write part is everything following the position. API clients acting as producers should write to the write part and then move the position forward as many bytes as it wrote. API clients acting as consumers should read the read part.
Generally, std::ostringstream or std::vector<char> are safer and simpler interfaces for buffers and should be preferred when possible. However they do not fit all use cases:
- std::ostringstream is preferrable and more convenient when appending existing data to the stream. But it is not suitable for interaction with C-like APIs that produce data in a char* given by the caller. The user would need to allocate a buffer outside the ostringsteam and then append the buffer to the ostringstream, which would imply unnecessary memory and cpu overheads.
- When using a C-like API that produces data in a char* given by the caller, std::vector is often good. The user can reserve as much memory as needed and then pass the underlying data array to the API. However, the following properties are sometimes advantageous for Managed_buffer_sequence:
- Vector has no practical way to put an exact bound on the memory usage. Managed_buffer_sequence uses a Grow_calculator which allows exact control over memory usage, including a maximum size.
- Vector has to copy all existing data when it grows. Managed_buffer_sequence never needs to copy data. Since it allows data to be non-contigous, it retains existing buffers while allocating new ones.
The main drawbacks of Managed_buffer_sequence are that it is non-standard, has a minimal feature set, and is non-contiguous.
This class never throws any exception.
- Template Parameters
-
Char_t | the type of elements stored in the buffer: typically unsigned char. |
Container_tp | The type of container to hold the buffers. This defaults to std::vector, but std::list is also possible. |
template<class Char_tp = unsigned char, template< class Element_tp, class Allocator_tp > class Container_tp = std::vector>
Ensure the total capacity - the sum of sizes of read part and write part - is at least the given number.
This may add a new buffer if needed. When the previous size is less than the default size, this may even add two buffers: the default buffer and one more. Therefore, the caller should not assume that all the added size resides within one buffer.
Existing buffer data will not move. The container of buffers may grow, which may move the Buffer objects which hold pointers to the data. Therefore, all iterators are invalidated by this.
- Parameters
-
requested_total_size | The requested total size of all read and write buffers. |
- Return values
-
success | The object now has at least the requested total size. The object may have been resized. |
exceeds_max_size | The existing size or the requested size exceeds either the maximum size. The object is unchanged. |
out_of_memory | The request could only be fulfilled by allocating more memory, but memory allocation failed. The object is unchanged. |