MySQL 9.0.0
Source Code Documentation
managed_buffer_sequence.h
Go to the documentation of this file.
1/* Copyright (c) 2023, 2024, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24/// @file managed_buffer_sequence.h
25///
26/// @brief Container class that provides a sequence of buffers to
27/// the caller.
28
29#ifndef MYSQL_BINLOG_EVENT_COMPRESSION_BUFFER_MANAGED_BUFFER_SEQUENCE_H
30#define MYSQL_BINLOG_EVENT_COMPRESSION_BUFFER_MANAGED_BUFFER_SEQUENCE_H
31
32#include <algorithm> // std::min
33#include <cassert> // assert
34#include <cstring> // std::memcpy
35#include <limits> // std::numeric_limits
36#include <vector> // std::vector
37
38#include "mysql/binlog/event/compression/buffer/buffer_view.h" // buffer::Buffer_view
39#include "mysql/binlog/event/compression/buffer/grow_calculator.h" // buffer::Grow_calculator
40#include "mysql/binlog/event/compression/buffer/grow_status.h" // buffer::Grow_status
41#include "mysql/binlog/event/compression/buffer/rw_buffer_sequence.h" // buffer::Rw_buffer_sequence
42#include "mysql/binlog/event/nodiscard.h" // NODISCARD
43#include "mysql/binlog/event/resource/allocator.h" // Allocator
44#include "mysql/binlog/event/resource/memory_resource.h" // Memory_resource
45
46#include "mysql/binlog/event/wrapper_functions.h" // BAPI_TRACE
47
48/// @addtogroup GroupLibsMysqlBinlogEvent
49/// @{
50
52
53// Forward declare Accessor so we can make it a friend
54namespace managed_buffer_sequence::unittest {
55template <class T>
57} // namespace managed_buffer_sequence::unittest
58
59/// Owned, non-contiguous, growable memory buffer.
60///
61/// This class never moves buffer data, but is non-contiguous. It is
62/// implemented as a container of Buffer objects.
63///
64/// Objects have a growable size, a movable position, and two
65/// buffer_sequence_view objects called the read part and the write
66/// part, which are accessible through the member functions @c
67/// read_part and @c write_part. The read part is everything
68/// preceding the position, and the write part is everything following
69/// the position. API clients acting as producers should write to the
70/// write part and then move the position forward as many bytes as it
71/// wrote. API clients acting as consumers should read the read part.
72///
73/// Generally, std::ostringstream or std::vector<char> are safer and
74/// simpler interfaces for buffers and should be preferred when
75/// possible. However they do not fit all use cases:
76///
77/// - std::ostringstream is preferrable and more convenient when
78/// appending existing data to the stream. But it is not suitable
79/// for interaction with C-like APIs that produce data in a char*
80/// given by the caller. The user would need to allocate a buffer
81/// outside the ostringsteam and then append the buffer to the
82/// ostringstream, which would imply unnecessary memory and cpu
83/// overheads.
84///
85/// - When using a C-like API that produces data in a char* given by
86/// the caller, std::vector is often good. The user can reserve as
87/// much memory as needed and then pass the underlying data array to
88/// the API. However, the following properties are sometimes
89/// advantageous for Managed_buffer_sequence:
90///
91/// - Vector has no practical way to put an exact bound on the
92/// memory usage. Managed_buffer_sequence uses a Grow_calculator
93/// which allows exact control over memory usage, including a
94/// maximum size.
95///
96/// - Vector has to copy all existing data when it grows.
97/// Managed_buffer_sequence never needs to copy data. Since it
98/// allows data to be non-contigous, it retains existing buffers
99/// while allocating new ones.
100///
101/// The main drawbacks of Managed_buffer_sequence are that it is
102/// non-standard, has a minimal feature set, and is non-contiguous.
103///
104/// This class never throws any exception.
105///
106/// @tparam Char_tp the type of elements stored in the buffer:
107/// typically unsigned char.
108///
109/// @tparam Container_tp The type of container to hold the buffers.
110/// This defaults to std::vector, but std::list is also possible.
111template <class Char_tp = unsigned char,
112 template <class Element_tp, class Allocator_tp> class Container_tp =
115 : public Rw_buffer_sequence<Char_tp, Container_tp> {
116 public:
118 // Would prefer to use:
119 // using typename Rw_buffer_sequence_t::Buffer_sequence_t;
120 // But that doesn't compile on Windows (maybe a compiler bug).
123 using typename Rw_buffer_sequence_t::Char_t;
127 using typename Rw_buffer_sequence_t::Size_t;
133
134 /// Construct a new, empty object.
135 ///
136 /// @param grow_calculator the policy to determine how much memory to
137 /// allocate, when new memory is needed
138 ///
139 /// @param memory_resource The memory_resource used to allocate new
140 /// memory, both for the container and for the buffers.
141 ///
142 /// @param default_buffer_count The initial size of the container.
143 /// This preallocates the container but not the buffers contained in
144 /// it.
146 const Grow_calculator_t &grow_calculator = Grow_calculator_t(),
147 const Memory_resource_t &memory_resource = Memory_resource_t(),
148 const Size_t default_buffer_count = 16)
150 Container_t(std::max(default_buffer_count, Size_t(1)),
151 Buffer_allocator_t(memory_resource)),
152 grow_calculator, memory_resource) {}
153
154 // Disallow copy/move. We can implement these in the future if we
155 // need them.
160
161 ~Managed_buffer_sequence() override { this->reset(0); }
162
163 /// Ensure the write part has at least the given size.
164 ///
165 /// This is only a convenience wrapper around @c
166 /// reserve_total_size.
167 ///
168 /// @param requested_write_size The requested size of the write
169 /// part.
170 ///
171 /// @retval success The write part now has at least the requested
172 /// size. The object may have been resized, following the rules of
173 /// the Grow_calculator.
174 ///
175 /// @retval exceeds_max_size Either size() or read_part.size() +
176 /// requested_write_size exceeds the max size configured in the
177 /// Grow_calculator. The object is unchanged.
178 ///
179 /// @retval out_of_memory The request could only be fulfilled by
180 /// allocating more memory, but memory allocation failed. The
181 /// object is unchanged.
182 [[NODISCARD]] Grow_status reserve_write_size(Size_t requested_write_size) {
183 auto read_size = this->read_part().size();
184 if (requested_write_size > std::numeric_limits<Size_t>::max() - read_size)
186 return reserve_total_size(read_size + requested_write_size);
187 }
188
189 /// Ensure the total capacity - the sum of sizes of read part and
190 /// write part - is at least the given number.
191 ///
192 /// This may add a new buffer if needed. When the previous size is
193 /// less than the default size, this may even add two buffers: the
194 /// default buffer and one more. Therefore, the caller should not
195 /// assume that all the added size resides within one buffer.
196 ///
197 /// Existing buffer data will not move. The container of buffers
198 /// may grow, which may move the Buffer objects which hold pointers
199 /// to the data. Therefore, all iterators are invalidated by this.
200 ///
201 /// @param requested_total_size The requested total size of all read
202 /// and write buffers.
203 ///
204 /// @retval success The object now has at least the requested total
205 /// size. The object may have been resized.
206 ///
207 /// @retval exceeds_max_size The existing size or the requested size
208 /// exceeds either the maximum size. The object is unchanged.
209 ///
210 /// @retval out_of_memory The request could only be fulfilled by
211 /// allocating more memory, but memory allocation failed. The
212 /// object is unchanged.
213 [[NODISCARD]] Grow_status reserve_total_size(Size_t requested_total_size) {
214 auto work = [&] {
215 auto capacity = this->capacity();
216 auto [error, new_capacity] =
217 m_grow_calculator.compute_new_size(capacity, requested_total_size);
219 if (new_capacity > capacity) {
220 if (allocate_and_add_buffer(new_capacity - capacity))
222 }
224 };
225 auto ret = work();
226 BAPI_LOG("info", BAPI_VAR(ret)
227 << " " << BAPI_VAR(requested_total_size) << " "
228 << BAPI_VAR(this->capacity()) << " "
230 return ret;
231 }
232
233 /// Reset the read part and the write part to size 0.
234 ///
235 /// This optionally keeps a given number of allocated buffers in the
236 /// write part, as well as a given amount of container capacity.
237 ///
238 /// @param keep_buffer_count The number of existing buffers to keep.
239 /// Using a nonzero value for this reduces container allocations
240 /// when this object is reused. If the container has fewer buffers,
241 /// the existing buffers will be kept and no more will be allocated.
242 /// If the container has more buffers, the excess buffers will be
243 /// deallocated.
244 ///
245 /// @param keep_container_capacity The amount of container capacity
246 /// to keep. Using a small nonzero value for this reduces container
247 /// allocations when this object is reused. This must be at least
248 /// the number of kept buffers plus two; otherwise it is modified to
249 /// that number. If the underlying container type is a vector, it
250 /// will only shrink if it would reduce the number of elements by
251 /// half.
252 void reset(Size_t keep_buffer_count = 1,
253 // NOLINTNEXTLINE(readability-magic-numbers)
254 Size_t keep_container_capacity = 16) {
256 // Move all buffers from read part to write part.
257 this->set_position(0);
258
259 // Skip over buffers we need to keep, and count them.
260 auto it = this->write_part().begin();
261 assert(std::distance(this->m_buffers.begin(), it) == 1);
262 Size_t kept_buffer_count = 0;
263 Size_t kept_size = 0;
264 for (; it != this->write_part().end() &&
265 kept_buffer_count < keep_buffer_count;
266 ++it) {
267 ++kept_buffer_count;
268 kept_size += it->size();
269 }
270
271 // Deallocate buffers we don't need to keep.
272 for (; it != this->write_part().end(); ++it) {
273 m_char_allocator.deallocate(it->data(), it->size());
274 *it = Buffer_view_t();
275 }
276
277 // Remove exceess container capacity.
278 keep_container_capacity =
279 std::max(keep_container_capacity, 2 + kept_buffer_count);
280 reset_container(m_buffers, keep_container_capacity);
281
282 // Reset Buffer_sequences
283 it = m_buffers.begin();
284 this->read_part() = Buffer_sequence_view_t(it, it, 0);
285 ++it;
286 this->write_part() =
287 Buffer_sequence_view_t(it, std::next(it, kept_buffer_count), kept_size);
288 }
289
290 /// Return a const reference to the grow calculator.
292 return m_grow_calculator;
293 }
294
295 /// Set the grow calculator.
296 void set_grow_calculator(const Grow_calculator_t &grow_calculator) {
297 m_grow_calculator = grow_calculator;
298 }
299
300 /// Append the given data.
301 ///
302 /// This will grow the buffer if needed. Then it writes the data to
303 /// the write part, and moves the position so that the written
304 /// becomes part of the read part instead of the write part.
305 ///
306 /// @param data The data to write
307 ///
308 /// @param size The number of bytes to write.
309 ///
310 /// @retval success The buffer already had enough capacity, or could
311 /// be grown without error. The data has been appended and the
312 /// position has been advanced `size` bytes.
313 ///
314 /// @retval out_of_memory An out of memory condition occurred when
315 /// allocating memory for the buffer. This object is unchanged.
316 ///
317 /// @retval exceeds_max_size The required size would exceed the
318 /// maximum specified by the Grow_calculator. This object is
319 /// unchanged.
321 auto grow_status = this->reserve_write_size(size);
322 if (grow_status != Grow_status::success) return grow_status;
323 const auto *remaining_data = data;
324 auto remaining_size = size;
325 auto buffer_it = this->write_part().begin();
326 while (remaining_size != 0) {
327 auto copy_size = std::min(buffer_it->size(), remaining_size);
328 std::memcpy(buffer_it->begin(), remaining_data, copy_size);
329 remaining_data += copy_size;
330 remaining_size -= copy_size;
331 ++buffer_it;
332 }
333 this->increase_position(size);
335 }
336
337 /// In debug mode, return a string that describes the internal
338 /// structure of this object, to use for debugging.
339 ///
340 /// @param show_contents If true, includes the buffer contents.
341 /// Otherwise, just pointers and sizes.
342 ///
343 /// @param indent If 0, put all info on one line. Otherwise, put
344 /// each field on its own line and indent the given number of
345 /// two-space levels.
346 std::string debug_string([[maybe_unused]] bool show_contents,
347 [[maybe_unused]] int indent) const override {
348#ifdef NDEBUG
349 return "";
350#else
351 std::string sep;
352 if (indent != 0)
353 sep = std::string(",\n") +
354 std::string(static_cast<std::string::size_type>(indent * 2), ' ');
355 else
356 sep = ", ";
357 int next_indent = (indent != 0) ? indent + 1 : 0;
359 // clang-format off
360 ss << "Managed_buffer_sequence(ptr=" << (const void *)this
361 << sep << Rw_buffer_sequence_t::debug_string(show_contents, next_indent)
363 << sep << "buffers.size=" << m_buffers.size()
364 << ")";
365 // clang-format on
366 return ss.str();
367#endif
368 }
369
370 /// In debug mode, return a string that describes the internal
371 /// structure of this object, to use for debugging.
372 ///
373 /// @param show_contents If true, includes the buffer contents.
374 /// Otherwise, just pointers and sizes.
375 std::string debug_string([[maybe_unused]] bool show_contents = false) const {
376 return debug_string(show_contents, 0);
377 }
378
379 protected:
380 /// Construct a new object from a given container, where both the
381 /// read part and the write part are size zero.
382 ///
383 /// The container will be moved. All elements in the container must
384 /// be null buffers.
385 ///
386 /// @param buffers Container of buffers. This must have at least one
387 /// element. All elements must be null buffers.
388 ///
389 /// @param grow_calculator determines how much memory to allocate
390 /// when new memory is needed.
391 ///
392 /// @param memory_resource The memory_resource used to allocate new
393 /// memory, both for the container and for the buffers.
395 const Grow_calculator_t &grow_calculator,
396 const Memory_resource_t &memory_resource)
397 : Rw_buffer_sequence_t(buffers.begin(), std::next(buffers.begin())),
398 m_grow_calculator(grow_calculator),
399 m_char_allocator(memory_resource),
400 m_buffers(std::move(buffers)) {
401#ifndef NDEBUG
402 assert(m_buffers.size() >= 1);
403 for (auto &buffer : m_buffers) {
404 assert(buffer.data() == nullptr);
405 assert(buffer.size() == 0);
406 }
407#endif
408 }
409
410 /// Allocate and add a new buffer.
411 ///
412 /// @param size The size of the new buffer that should be allocated.
413 ///
414 /// @retval true An out of memory condition occurred, and the
415 /// function did not produce any side effects.
416 ///
417 /// @retval false The operation succeeded, and the object now has at
418 /// least the requested size.
420 // Allocate the data.
421 auto data = m_char_allocator.allocate(size);
422 if (data == nullptr) {
423 BAPI_LOG("info", "error: out of memory allocating " << size << " bytes");
424 return true;
425 }
426 // Add the buffer to the container.
427 if (add_buffer(data, size)) {
428 BAPI_LOG("info", "error: out of memory growing container of "
429 << m_buffers.size() << " elements");
431 return true;
432 }
433 return false;
434 }
435
436 /// Insert the given buffer in the container, appending it to the
437 /// write part.
438 ///
439 /// @param buffer_data The buffer.
440 ///
441 /// @param buffer_size The buffer size.
442 ///
443 /// @retval false Success.
444 ///
445 /// @retval true An out of memory error occurred when growing the
446 /// container.
447 [[NODISCARD]] bool add_buffer(Char_t *buffer_data, Size_t buffer_size) {
449 auto [write_begin, write_end, write_size] =
450 this->get_boundaries(this->write_part());
451 if (write_end == m_buffers.end()) {
452 // Compute relative positions for all iterators.
453 auto [read_begin, read_end, read_size] =
454 this->get_boundaries(this->read_part());
455 auto read_end_offset = std::distance(read_begin, read_end);
456 auto write_begin_offset = std::distance(read_begin, write_begin);
457 auto write_end_offset = std::distance(read_begin, write_end);
458 // Insert in container, and handle the out-of-memory case.
459 try {
460 m_buffers.emplace_back(buffer_data, buffer_size);
461 } catch (...) {
462 BAPI_LOG("info", "error: out of memory growing container");
463 return true;
464 }
465 // Compute new iterators based on relative position from new
466 // beginning.
467 read_begin = m_buffers.begin();
468 read_end = std::next(read_begin, read_end_offset);
469 write_begin = std::next(read_begin, write_begin_offset);
470 write_end = std::next(read_begin, write_end_offset + 1);
471 // Update Buffer_sequence objects with new iterators.
472 this->read_part() =
473 Buffer_sequence_view_t(read_begin, read_end, read_size);
474 } else {
475 *write_end = Buffer_view_t(buffer_data, buffer_size);
476 ++write_end;
477 }
478 this->write_part() = Buffer_sequence_view_t(write_begin, write_end,
479 write_size + buffer_size);
480 return false;
481 }
482
483 using List_t = typename std::list<Buffer_view_t, Buffer_allocator_t>;
484 using List_iterator_t = typename List_t::iterator;
485 using Vector_t = typename std::vector<Buffer_view_t, Buffer_allocator_t>;
486 using Vector_iterator_t = typename Vector_t::iterator;
487
488 /// `std::vector`-specific function to reset the container.
489 ///
490 /// This shrinks the vector to keep_container_capacity if it is bigger
491 /// than twice keep_container_capacity.
492 ///
493 /// @param[in,out] container Reference to the vector to be reset.
494 ///
495 /// @param keep_container_capacity Keep a number of elements in the
496 /// vector, to save on future vector resize operations. If the
497 /// number of elements is at least twice this number, the vector
498 /// size is reduced to this number.
499 ///
501 Size_t keep_container_capacity) {
502 if (container.capacity() > 2 * keep_container_capacity) {
503 container.resize(keep_container_capacity);
504 container.shrink_to_fit();
505 }
506 }
507
508 /// `std::list`-specific function to reset the container.
509 ///
510 /// This shrinks the list to @c keep_container_capacity if it is
511 /// bigger than @c keep_container_capacity.
512 ///
513 /// @param[in,out] container Reference to the list to be reset.
514 ///
515 /// @param keep_container_capacity Keep this number of elements in
516 /// the list, in order to save future allocations of list nodes.
517 ///
519 Size_t keep_container_capacity) {
520 if (container.size() > keep_container_capacity)
521 container.resize(keep_container_capacity);
522 }
523
524 private:
525 /// Determines how much memory to allocate when new memory is
526 /// needed.
528
529 /// Allocator to allocate buffer data (characters).
531
532 /// Container of buffers.
534
535 /// Open the class internals to any class named Accessor<T>, for
536 /// some T.
537 ///
538 /// This may be used by unit tests that need access to internals.
539 ///
540 /// For example, if unittest SomeTest needs access to member `int m`,
541 /// define the helper class:
542 /// @code
543 /// namespace
544 /// mysql::binlog::event::compression::buffer::managed_buffer_sequence::unittest
545 /// { template<> class Accessor<SomeTest> {
546 /// static int &m(Managed_buffer_sequence &rbs) { return rbs.m; }
547 /// };
548 /// }
549 /// @endcode
550 template <class T>
552};
553
554} // namespace mysql::binlog::event::compression::buffer
555
556/// @}
557
558#endif // MYSQL_BINLOG_EVENT_COMPRESSION_BUFFER_MANAGED_BUFFER_SEQUENCE_H
Class that groups a pointer+size as one object, without managing the memory for it.
Sequence of memory buffers.
Definition: buffer_sequence_view.h:72
Iterator_t begin()
Iterator to the first buffer.
Definition: buffer_sequence_view.h:117
Size_t size() const
Return the total size of all buffers.
Definition: buffer_sequence_view.h:164
Iterator_t end()
Iterator to the last buffer.
Definition: buffer_sequence_view.h:120
mysql::binlog::event::resource::Allocator< Buffer_view_t > Buffer_allocator_t
Definition: buffer_sequence_view.h:78
Description of a heuristic to determine how much memory to allocate.
Definition: grow_calculator.h:68
Result_t compute_new_size(Size_t old_size, Size_t requested_size) const
Compute the new size.
Definition: grow_calculator.cpp:39
Size_t get_max_size() const
Definition: grow_constraint.cpp:32
std::string debug_string() const
In debug mode, return a string that describes the internal structure of this object,...
Definition: grow_constraint.h:124
Owned, non-contiguous, growable memory buffer.
Definition: managed_buffer_sequence.h:115
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,...
Definition: managed_buffer_sequence.h:346
typename std::list< Buffer_view_t, Buffer_allocator_t > List_t
Definition: managed_buffer_sequence.h:483
~Managed_buffer_sequence() override
Definition: managed_buffer_sequence.h:161
Char_allocator_t m_char_allocator
Allocator to allocate buffer data (characters).
Definition: managed_buffer_sequence.h:530
bool add_buffer(Char_t *buffer_data, Size_t buffer_size)
Insert the given buffer in the container, appending it to the write part.
Definition: managed_buffer_sequence.h:447
std::string debug_string(bool show_contents=false) const
In debug mode, return a string that describes the internal structure of this object,...
Definition: managed_buffer_sequence.h:375
Grow_calculator Grow_calculator_t
Definition: managed_buffer_sequence.h:128
typename Buffer_sequence_view_t::Buffer_allocator_t Buffer_allocator_t
Definition: managed_buffer_sequence.h:130
Managed_buffer_sequence & operator=(Managed_buffer_sequence &)=delete
static void reset_container(List_t &container, Size_t keep_container_capacity)
std::list-specific function to reset the container.
Definition: managed_buffer_sequence.h:518
typename std::vector< Buffer_view_t, Buffer_allocator_t > Vector_t
Definition: managed_buffer_sequence.h:485
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.
Definition: managed_buffer_sequence.h:252
Grow_status write(const Char_t *data, Size_t size)
Append the given data.
Definition: managed_buffer_sequence.h:320
Container_t m_buffers
Container of buffers.
Definition: managed_buffer_sequence.h:533
typename List_t::iterator List_iterator_t
Definition: managed_buffer_sequence.h:484
typename Buffer_sequence_view_t::Char_t Char_t
Definition: rw_buffer_sequence.h:110
typename Buffer_sequence_view_t::Container_t Container_t
Definition: rw_buffer_sequence.h:116
const Grow_calculator_t & get_grow_calculator() const
Return a const reference to the grow calculator.
Definition: managed_buffer_sequence.h:291
Grow_status reserve_write_size(Size_t requested_write_size)
Ensure the write part has at least the given size.
Definition: managed_buffer_sequence.h:182
typename Vector_t::iterator Vector_iterator_t
Definition: managed_buffer_sequence.h:486
typename Buffer_sequence_view_t::Size_t Size_t
Definition: rw_buffer_sequence.h:111
Managed_buffer_sequence & operator=(Managed_buffer_sequence &&)=delete
mysql::binlog::event::resource::Memory_resource Memory_resource_t
Definition: managed_buffer_sequence.h:132
Buffer_sequence_view< Char_tp, Container_tp > Buffer_sequence_view_t
Definition: managed_buffer_sequence.h:121
Grow_calculator_t m_grow_calculator
Determines how much memory to allocate when new memory is needed.
Definition: managed_buffer_sequence.h:527
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 numb...
Definition: managed_buffer_sequence.h:213
static void reset_container(Vector_t &container, Size_t keep_container_capacity)
std::vector-specific function to reset the container.
Definition: managed_buffer_sequence.h:500
void set_grow_calculator(const Grow_calculator_t &grow_calculator)
Set the grow calculator.
Definition: managed_buffer_sequence.h:296
bool allocate_and_add_buffer(Size_t size)
Allocate and add a new buffer.
Definition: managed_buffer_sequence.h:419
typename Buffer_sequence_view_t::Buffer_view_t Buffer_view_t
Definition: rw_buffer_sequence.h:113
Managed_buffer_sequence(Container_t buffers, const Grow_calculator_t &grow_calculator, const Memory_resource_t &memory_resource)
Construct a new object from a given container, where both the read part and the write part are size z...
Definition: managed_buffer_sequence.h:394
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.
Definition: managed_buffer_sequence.h:145
Non-owning manager for a fixed sequence of memory buffers, which is split into a read part and a writ...
Definition: rw_buffer_sequence.h:107
const Buffer_sequence_view_t & write_part() const
Return a const reference to the write part.
Definition: rw_buffer_sequence.h:225
Size_t capacity() const
Return the current size, i.e., total size of all buffers.
Definition: rw_buffer_sequence.h:216
typename Buffer_sequence_view_t::Iterator_t Iterator_t
Definition: rw_buffer_sequence.h:117
void increase_position(Size_t delta)
Move the position right, relative to the current position.
Definition: rw_buffer_sequence.h:187
const Buffer_sequence_view_t & read_part() const
Return a const reference to the read part.
Definition: rw_buffer_sequence.h:219
void set_position(Size_t new_position)
Set the specified absolute position.
Definition: rw_buffer_sequence.h:168
typename Buffer_sequence_view_t::Char_t Char_t
Definition: rw_buffer_sequence.h:110
typename Buffer_sequence_view_t::Container_t Container_t
Definition: rw_buffer_sequence.h:116
typename Buffer_sequence_view_t::Size_t Size_t
Definition: rw_buffer_sequence.h:111
typename Buffer_sequence_view_t::Const_iterator_t Const_iterator_t
Definition: rw_buffer_sequence.h:118
typename Buffer_sequence_view_t::Buffer_view_t Buffer_view_t
Definition: rw_buffer_sequence.h:113
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.
Definition: rw_buffer_sequence.h:477
virtual std::string debug_string(bool show_contents, int indent) const
In debug mode, return a string that describes the internal structure of this object,...
Definition: rw_buffer_sequence.h:239
constexpr T * allocate(size_type n)
Use the Memory_resource to allocate the given number of elements of type T.
Definition: allocator.h:84
constexpr void deallocate(T *p, size_type size)
Use the Memory_resource to deallocate the given pointer.
Definition: allocator.h:95
Polymorphism-free memory resource class with custom allocator and deallocator functions.
Definition: memory_resource.h:88
void * data() const noexcept
Definition: buffer.h:119
size_t size() const noexcept
Definition: buffer.h:120
Allocator class that uses a polymorphic Memory_resource to allocate memory.
Class that wraps resources in a polymorphic manner.
void error(const char *format,...)
Definition: atomics_array.h:39
bool distance(const dd::Spatial_reference_system *srs, const Geometry *g1, const Geometry *g2, double *distance, bool *is_null) noexcept
Computes the distance between two geometries.
Definition: distance.cc:40
Definition: buffer_sequence_view.h:51
Grow_status
Error statuses for classes that use Grow_calculator.
Definition: grow_status.h:38
@ exceeds_max_size
A grow operation could not be performed because there is a configured maximum size.
@ out_of_memory
A grow operation failed because memory allocation failed.
const char * begin(const char *const c)
Definition: base64.h:44
size_t size(const char *const c)
Definition: base64.h:46
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:418
size_t buffer_size(const ConstBufferSequence &buffers) noexcept
Definition: buffer.h:313
Definition: gcs_xcom_synode.h:64
std::basic_ostringstream< char, std::char_traits< char >, ut::allocator< char > > ostringstream
Specialization of basic_ostringstream which uses ut::allocator.
Definition: ut0new.h:2871
std::vector< T, ut::allocator< T > > vector
Specialization of vector which uses allocator.
Definition: ut0new.h:2875
#define NODISCARD
The function attribute [[NODISCARD]] is a replacement for [[nodiscard]] to workaround a gcc bug.
Definition: nodiscard.h:47
Container class that provides a sequence of buffers to the caller.
Contains wrapper functions for memory allocation and deallocation.
#define BAPI_LOG(x, y)
Definition: wrapper_functions.h:67
#define BAPI_TRACE
Definition: wrapper_functions.h:65
#define BAPI_VAR(v)
Definition: wrapper_functions.h:68