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