23#include <boost/interprocess/smart_ptr/shared_ptr.hpp>
24#include <boost/move/make_unique.hpp>
25#include <boost/compressed_pair.hpp>
275template<
typename Allocator_t,
bool SHARING>
298 static_assert(std::is_same_v<typename Allocator::value_type, value_type>,
299 "Allocator template param must be of form A<V> where V is our value_type.");
705 template<typename Emit_blob_func>
707 log::Logger* logger_ptr =
nullptr);
724 template<typename Blob_container>
726 log::Logger* logger_ptr =
nullptr);
745 template<typename Blob_ptr_container>
747 log::Logger* logger_ptr =
nullptr);
809 log::Logger* logger_ptr =
nullptr) const;
1246 template<typename Emit_blob_func, typename Share_after_split_left_func>
1248 Emit_blob_func&& emit_blob_func,
1249 log::Logger* logger_ptr,
1250 Share_after_split_left_func&& share_after_split_left_func);
1303 using Pointer_raw =
typename std::allocator_traits<Allocator>::pointer;
1339 Deleter_raw(Deleter_raw&& moved_src);
1498 boost::shared_ptr<value_type[]>,
1499 boost::movelib::unique_ptr<value_type[]>>,
1501 boost::interprocess::shared_ptr
1503 boost::movelib::unique_ptr<value_type, Deleter_raw>>>;
1670template<
typename Allocator_t,
bool SHARING>
1672 m_alloc_and_buf_ptr(alloc_raw_src),
1680template<
typename Allocator_t,
bool SHARING>
1689template<
typename Allocator_t,
bool SHARING>
1698template<
typename Allocator_t,
bool SHARING>
1701 Basic_blob(std::allocator_traits<
Allocator>::select_on_container_copy_construction(src.alloc_raw()))
1711template<
typename Allocator_t,
bool SHARING>
1714 m_alloc_and_buf_ptr(std::move(moved_src.alloc_raw())),
1721 swap_impl(moved_src, logger_ptr);
1724template<
typename Allocator_t,
bool SHARING>
1727template<
typename Allocator_t,
bool SHARING>
1734 if constexpr(S_SHARING)
1740 if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value)
1790template<
typename Allocator_t,
bool SHARING>
1796template<
typename Allocator_t,
bool SHARING>
1800 if (
this != &moved_src)
1803 if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value)
1805 alloc_raw() = std::move(moved_src.alloc_raw());
1816 make_zero(logger_ptr);
1819 swap_impl(moved_src, logger_ptr);
1827template<
typename Allocator_t,
bool SHARING>
1831 return assign(std::move(moved_src));
1834template<
typename Allocator_t,
bool SHARING>
1848 "swapping <=> Blob [" << &other <<
"] (internal buffer sized "
1849 "[" << other.capacity() <<
"]).");
1864 swap(buf_ptr(), other.buf_ptr());
1870#pragma GCC diagnostic push
1871#pragma GCC diagnostic ignored "-Wpragmas"
1872#pragma GCC diagnostic ignored "-Wunknown-warning-option"
1873#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1875 swap(m_capacity, other.m_capacity);
1876 swap(m_size, other.m_size);
1877 swap(m_start, other.m_start);
1879#pragma GCC diagnostic pop
1886template<
typename Allocator_t,
bool SHARING>
1892 if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value)
1894 if (&alloc_raw() != &other.alloc_raw())
1896 swap(alloc_raw(), other.alloc_raw());
1907 swap_impl(other, logger_ptr);
1910template<
typename Allocator_t,
bool SHARING>
1914 return blob1.swap(blob2, logger_ptr);
1917template<
typename Allocator_t,
bool SHARING>
1920 static_assert(S_SHARING,
1921 "Do not invoke (and thus instantiate) share() or derived methods unless you set the SHARING "
1922 "template parameter to true. Sharing will be enabled at a small perf cost; see class doc header.");
1927 Basic_blob sharing_blob{alloc_raw(), logger_ptr};
1928 assert(!sharing_blob.buf_ptr());
1929 sharing_blob.buf_ptr() = buf_ptr();
1931 sharing_blob.m_capacity = m_capacity;
1932 sharing_blob.m_start = m_start;
1933 sharing_blob.m_size = m_size;
1939 (
"Blob [" <<
this <<
"] shared with new Blob [" << &sharing_blob <<
"]; ref-count incremented.");
1942 return sharing_blob;
1945template<
typename Allocator_t,
bool SHARING>
1949 if (lt_size > size())
1958 "[" << lt_size <<
"] values into that one and leaving the remaining "
1959 "[" << (size() - lt_size) <<
"] in this one.");
1962 auto sharing_blob = share(logger_ptr);
1963 sharing_blob.resize(lt_size);
1964 start_past_prefix_inc(lt_size);
1966 return sharing_blob;
1969template<
typename Allocator_t,
bool SHARING>
1973 if (rt_size > size())
1978 const auto lt_size = size() - rt_size;
1983 "the last [" << rt_size <<
"] values into that one and leaving the "
1984 "remaining [" << lt_size <<
"] in this one.");
1987 auto sharing_blob = share(logger_ptr);
1989 sharing_blob.start_past_prefix_inc(lt_size);
1991 return sharing_blob;
1994template<
typename Allocator_t,
bool SHARING>
1995template<
typename Emit_blob_func,
typename Share_after_split_left_func>
1998 Share_after_split_left_func&& share_after_split_left_func)
2007 "adjacent sharing sub-Blobs of size [" << size <<
"] each "
2008 "(last one possibly smaller).");
2013 emit_blob_func(share_after_split_left_func(size, logger_ptr));
2019 make_zero(logger_ptr);
2023template<
typename Allocator_t,
bool SHARING>
2024template<
typename Emit_blob_func>
2026 Emit_blob_func&& emit_blob_func,
2029 share_after_split_equally_impl(size, headless_pool, std::move(emit_blob_func), logger_ptr,
2032 return share_after_split_left(lt_size, logger_ptr);
2036template<
typename Allocator_t,
bool SHARING>
2037template<
typename Blob_container>
2043 assert(out_blobs_ptr);
2044 share_after_split_equally(size, headless_pool, [&](
Basic_blob&& blob_moved)
2046 out_blobs_ptr->push_back(std::move(blob_moved));
2050template<
typename Allocator_t,
bool SHARING>
2051template<
typename Blob_ptr_container>
2054 Blob_ptr_container* out_blobs_ptr,
2060 using Ptr =
typename Blob_ptr_container::value_type;
2062 assert(out_blobs_ptr);
2064 share_after_split_equally(size, headless_pool, [&](
Basic_blob&& blob_moved)
2066 out_blobs_ptr->push_back(Ptr{
new Basic_blob{std::move(blob_moved)}});
2070template<
typename Allocator_t,
bool SHARING>
2074 static_assert(SHARING,
2075 "blobs_sharing() would only make sense on `Basic_blob`s with SHARING=true. "
2076 "Even if we were to allow this to instantiate (compile) it would always return false.");
2078 return ((!blob1.
zero()) && (!blob2.
zero()))
2079 && ((&blob1 == &blob2)
2086template<
typename Allocator_t,
bool SHARING>
2089 return zero() ? 0 : m_size;
2092template<
typename Allocator_t,
bool SHARING>
2095 return zero() ? 0 : m_start;
2098template<
typename Allocator_t,
bool SHARING>
2104template<
typename Allocator_t,
bool SHARING>
2107 return zero() ? 0 : m_capacity;
2110template<
typename Allocator_t,
bool SHARING>
2116template<
typename Allocator_t,
bool SHARING>
2119 reserve_impl(new_capacity,
false, logger_ptr);
2122template<
typename Allocator_t,
bool SHARING>
2125 reserve_impl(new_capacity,
true, logger_ptr);
2128template<
typename Allocator_t,
bool SHARING>
2131 using boost::make_shared_noinit;
2132 using boost::make_shared;
2133 using boost::shared_ptr;
2134 using std::numeric_limits;
2139 assert((zero() || ((new_capacity <= m_capacity) && (m_capacity > 0)))
2140 &&
"Basic_blob intentionally disallows reserving N>M>0, where M is current capacity. make_zero() first.");
2146 if (zero() && (new_capacity != 0))
2152 "allocating internal buffer sized [" << new_capacity <<
"]; "
2153 "will zero-fill? = [" << clear_on_alloc <<
"].");
2156 if (new_capacity <=
size_type(numeric_limits<difference_type>::max()))
2163 if constexpr(S_IS_VANILLA_ALLOC)
2176 if constexpr(S_SHARING)
2182 buf_ptr().reset(clear_on_alloc ? (
new value_type[new_capacity]()) : (
new value_type[new_capacity]),
2184 [logger_ptr, original_blob =
this, new_capacity]
2188 FLOW_LOG_TRACE(
"Deallocating internal buffer sized [" << new_capacity <<
"] originally allocated by "
2189 "Blob [" << original_blob <<
"]; note that Blob may now be gone and furthermore another "
2190 "Blob might live at that address now. A message immediately preceding this one should "
2191 "indicate the last Blob to give up ownership of the internal buffer.");
2193 delete [] buf_ptr_to_delete;
2200 buf_ptr() = clear_on_alloc ? make_shared<value_type[]>(new_capacity)
2201 : make_shared_noinit<value_type[]>(new_capacity);
2206 buf_ptr() = clear_on_alloc ? boost::movelib::make_unique<value_type[]>(new_capacity)
2207 : boost::movelib::make_unique_definit<value_type[]>(new_capacity);
2217 const auto ptr = alloc_raw().allocate(new_capacity);
2219 if constexpr(S_SHARING)
2221 buf_ptr().reset(ptr,
2270 buf_ptr().get_deleter() =
Deleter_raw{alloc_raw(), new_capacity};
2271 buf_ptr().reset(ptr);
2276 memset(ptr.get(), 0, new_capacity);
2321 assert(
false &&
"Enormous or corrupt new_capacity?!");
2348 m_capacity = new_capacity;
2358 assert(capacity() >= new_capacity);
2361template<
typename Allocator_t,
bool SHARING>
2365 resize_impl(new_size,
false, new_start_or_unchanged, logger_ptr);
2368template<
typename Allocator_t,
bool SHARING>
2372 resize_impl(new_size,
true, new_start_or_unchanged, logger_ptr);
2375template<
typename Allocator_t,
bool SHARING>
2379 auto& new_start = new_start_or_unchanged;
2380 if (new_start == S_UNCHANGED)
2382 new_start = start();
2385 const size_type min_capacity = new_start + new_size;
2392 reserve_impl(min_capacity, clear_on_alloc, logger_ptr);
2393 assert(capacity() >= min_capacity);
2398 m_start = new_start;
2402 assert(size() == new_size);
2403 assert(start() == new_start);
2406template<
typename Allocator_t,
bool SHARING>
2409 resize(((start() + size()) > prefix_size)
2410 ? (start() + size() - prefix_size)
2416template<
typename Allocator_t,
bool SHARING>
2419 assert((prefix_size_inc >= 0) || (start() >=
size_type(-prefix_size_inc)));
2420 start_past_prefix(start() + prefix_size_inc);
2423template<
typename Allocator_t,
bool SHARING>
2431template<
typename Allocator_t,
bool SHARING>
2441 if constexpr(SHARING)
2444 "[" << capacity() <<
"]; deallocation will immediately follow if no sharing "
2445 "`Blob`s remain; else ref-count merely decremented.");
2450 "[" << capacity() <<
"].");
2458template<
typename Allocator_t,
bool SHARING>
2467 resize(n, 0, logger_ptr);
2470 emplace_copy(const_begin(), src, logger_ptr);
2477template<
typename Allocator_t,
bool SHARING>
2486 assert(valid_iterator(dest));
2488 const Iterator dest_it = iterator_sans_const(dest);
2499 "memory area [" <<
static_cast<const void*
>(src_data) <<
"] sized "
2500 "[" << n <<
"] to internal buffer at offset [" << (dest - const_begin()) <<
"].");
2503 assert(derefable_iterator(dest_it));
2507 assert(((dest_it + n) <= src_data) || ((src_data + n) <= dest_it));
2521#pragma GCC diagnostic push
2522#pragma GCC diagnostic ignored "-Wpragmas"
2523#pragma GCC diagnostic ignored "-Wunknown-warning-option"
2524#pragma GCC diagnostic ignored "-Wstringop-overflow"
2525#pragma GCC diagnostic ignored "-Wrestrict"
2531 memcpy(dest_it, src_data, n);
2533#pragma GCC diagnostic pop
2539template<
typename Allocator_t,
bool SHARING>
2548 assert(valid_iterator(src));
2553 const auto dest_data =
static_cast<Iterator>(dest.data());
2559 "memory area [" <<
static_cast<const void*
>(dest_data) <<
"] sized "
2560 "[" << n <<
"] from internal buffer offset [" << (src - const_begin()) <<
"].");
2563 assert(derefable_iterator(src));
2566 assert(((src + n) <= dest_data) || ((dest_data + n) <= src));
2569#pragma GCC diagnostic push
2570#pragma GCC diagnostic ignored "-Wpragmas"
2571#pragma GCC diagnostic ignored "-Wunknown-warning-option"
2572#pragma GCC diagnostic ignored "-Wstringop-overflow"
2573#pragma GCC diagnostic ignored "-Wrestrict"
2574 memcpy(dest_data, src, n);
2575#pragma GCC diagnostic pop
2581template<
typename Allocator_t,
bool SHARING>
2587 assert(derefable_iterator(first));
2588 assert(valid_iterator(past_last));
2590 const Iterator dest = iterator_sans_const(first);
2592 if (past_last > first)
2594 const auto n_moved =
size_type(const_end() - past_last);
2599#pragma GCC diagnostic push
2600#pragma GCC diagnostic ignored "-Wpragmas"
2601#pragma GCC diagnostic ignored "-Wunknown-warning-option"
2602#pragma GCC diagnostic ignored "-Wstringop-overflow"
2603#pragma GCC diagnostic ignored "-Wrestrict"
2604 memmove(dest, iterator_sans_const(past_last), n_moved);
2605#pragma GCC diagnostic pop
2609 m_size -= (past_last - first);
2617template<
typename Allocator_t,
bool SHARING>
2622 return *const_begin();
2625template<
typename Allocator_t,
bool SHARING>
2630 return const_end()[-1];
2633template<
typename Allocator_t,
bool SHARING>
2641template<
typename Allocator_t,
bool SHARING>
2649template<
typename Allocator_t,
bool SHARING>
2653 return const_front();
2656template<
typename Allocator_t,
bool SHARING>
2660 return const_back();
2663template<
typename Allocator_t,
bool SHARING>
2667 return const_cast<Basic_blob*
>(
this)->begin();
2670template<
typename Allocator_t,
bool SHARING>
2690 const auto raw_or_fancy_buf_ptr = buf_ptr().get();
2691 return &(*raw_or_fancy_buf_ptr) + m_start;
2694template<
typename Allocator_t,
bool SHARING>
2698 return zero() ? const_begin() : (const_begin() + size());
2701template<
typename Allocator_t,
bool SHARING>
2705 return zero() ? begin() : (begin() + size());
2708template<
typename Allocator_t,
bool SHARING>
2712 return const_begin();
2715template<
typename Allocator_t,
bool SHARING>
2719 return const_begin();
2722template<
typename Allocator_t,
bool SHARING>
2729template<
typename Allocator_t,
bool SHARING>
2736template<
typename Allocator_t,
bool SHARING>
2740 return const_begin();
2743template<
typename Allocator_t,
bool SHARING>
2750template<
typename Allocator_t,
bool SHARING>
2753 return empty() ? (it == const_end())
2757template<
typename Allocator_t,
bool SHARING>
2760 return empty() ? false
2764template<
typename Allocator_t,
bool SHARING>
2771template<
typename Allocator_t,
bool SHARING>
2774 return boost::asio::const_buffer{const_data(), size()};
2777template<
typename Allocator_t,
bool SHARING>
2780 return boost::asio::mutable_buffer{data(), size()};
2783template<
typename Allocator_t,
bool SHARING>
2790template<
typename Allocator_t,
bool SHARING>
2793 return m_alloc_and_buf_ptr.second();
2796template<
typename Allocator_t,
bool SHARING>
2800 return const_cast<Basic_blob*
>(
this)->buf_ptr();
2803template<
typename Allocator_t,
bool SHARING>
2806 return m_alloc_and_buf_ptr.first();
2809template<
typename Allocator_t,
bool SHARING>
2813 return const_cast<Basic_blob*
>(
this)->alloc_raw();
2817template<
typename Allocator_t,
bool SHARING>
2825template<
typename Allocator_t,
bool SHARING>
2829 m_alloc_raw(std::in_place, alloc_raw_src),
2835template<
typename Allocator_t,
bool SHARING>
2846template<
typename Allocator_t,
bool SHARING>
2849template<
typename Allocator_t,
bool SHARING>
2855 if (
this != &moved_src)
2858 swap(m_buf_sz, moved_src.m_buf_sz);
2869 if (!moved_src.m_alloc_raw)
2872 m_alloc_raw.reset();
2877 const auto& src_alloc_raw = *moved_src.m_alloc_raw;
2878 if ((!m_alloc_raw) || (*m_alloc_raw != src_alloc_raw))
2880 m_alloc_raw.emplace(src_alloc_raw);
2885 moved_src.m_alloc_raw.reset();
2892template<
typename Allocator_t,
bool SHARING>
2906 m_alloc_raw.reset();
2911 if ((!m_alloc_raw) || (*m_alloc_raw != src_alloc_raw))
2913 m_alloc_raw.emplace(src_alloc_raw);
2921template<
typename Allocator_t,
bool SHARING>
2927 m_alloc_raw->deallocate(to_delete, m_buf_sz);
Interface that the user should implement, passing the implementing Logger into logging classes (Flow'...
virtual bool should_log(Sev sev, const Component &component) const =0
Given attributes of a hypothetical message that would be logged, return true if that message should b...
Internal deleter functor used if and only if S_IS_VANILLA_ALLOC is false and therefore only with Buf_...
std::optional< Allocator > m_alloc_raw
See ctor: the allocator that operator()() shall use to deallocate.
typename std::allocator_traits< Allocator >::pointer Pointer_raw
Short-hand for the allocator's pointer type, pointing to Basic_blob::value_type.
size_type m_buf_sz
See ctor and operator()(): the size of the buffer to deallocate.
Pointer_raw pointer
For boost::interprocess::shared_ptr and unique_ptr compliance (hence the irregular capitalization).
void operator()(Pointer_raw to_delete)
Deallocates using Allocator::deallocate(), passing-in the supplied pointer (to value_type) to_delete ...
Deleter_raw(const Deleter_raw &src)
Copy-construction which may be required when we are used in boost::interprocess::shared_ptr which as ...
Deleter_raw & operator=(Deleter_raw &&moved_src)
Move-assignment which is required when we are used in unique_ptr.
Deleter_raw()
Default ctor: Deleter must never be invoked to delete anything in this state; suitable only for a nul...
A hand-optimized and API-tweaked replacement for vector<uint8_t>, i.e., buffer of bytes inside an all...
std::conditional_t< S_IS_VANILLA_ALLOC, std::conditional_t< S_SHARING, boost::shared_ptr< value_type[]>, boost::movelib::unique_ptr< value_type[]> >, std::conditional_t< S_SHARING, boost::interprocess::shared_ptr< value_type, Allocator, Deleter_raw >, boost::movelib::unique_ptr< value_type, Deleter_raw > > > Buf_ptr
The smart-pointer type used for buf_ptr(); a custom-allocator-and-SHM-friendly impl and parameterizat...
size_type start() const
Returns the offset between begin() and the start of the internally allocated buffer.
~Basic_blob()
Destructor that drops *this ownership of the allocated internal buffer if any, as by make_zero(); if ...
size_type m_capacity
See capacity(); but m_capacity is meaningless (and containing unknown value) if !buf_ptr() (i....
void start_past_prefix_inc(difference_type prefix_size_inc)
Like start_past_prefix() but shifts the current prefix position by the given incremental value (posit...
const value_type & const_back() const
Returns reference to immutable last element.
Const_iterator cend() const
Synonym of const_end().
Iterator pointer
For container compliance (hence the irregular capitalization): pointer to element.
value_type const * const_data() const
Equivalent to const_begin().
Const_iterator const_end() const
Returns pointer one past immutable last element; empty() is possible.
void resize(size_type size, size_type start_or_unchanged=S_UNCHANGED, log::Logger *logger_ptr=nullptr)
Guarantees post-condition size() == size and start() == start; no values in pre-call range [begin(),...
Basic_blob(const Allocator &alloc_raw_src={})
Constructs blob with zero() == true.
Basic_blob(Basic_blob &&moved_src, log::Logger *logger_ptr=nullptr) noexcept
Move constructor, constructing a blob exactly internally equal to pre-call moved_src,...
size_type m_start
See start(); but m_start is meaningless (and containing unknown value) if !buf_ptr() (i....
size_type size() const
Returns number of elements stored, namely end() - begin().
void start_past_prefix(size_type prefix_size)
Restructures blob to consist of an internally allocated buffer and a [begin(), end) range starting at...
bool empty() const
Returns size() == 0.
size_type assign_copy(const boost::asio::const_buffer &src, log::Logger *logger_ptr=nullptr)
Replaces logical contents with a copy of the given non-overlapping area anywhere in memory.
Allocator get_allocator() const
Returns a copy of the internally cached Allocator as set by a constructor or assign() or assignment-o...
void share_after_split_equally(size_type size, bool headless_pool, Emit_blob_func &&emit_blob_func, log::Logger *logger_ptr=nullptr)
Identical to successively performing share_after_split_left(size) until this->empty() == true; the re...
value_type const * Const_iterator
Type for iterator pointing into an immutable structure of this type.
Basic_blob & operator=(Basic_blob &&moved_src) noexcept
Move assignment operator (no logging): equivalent to assign(std::move(moved_src)).
std::ptrdiff_t difference_type
Type for difference of size_types.
Const_iterator cbegin() const
Synonym of const_begin().
Const_iterator sub_copy(Const_iterator src, const boost::asio::mutable_buffer &dest, log::Logger *logger_ptr=nullptr) const
The opposite of emplace_copy() in every way, copying a sub-blob onto a target memory area.
void swap(Basic_blob &other, log::Logger *logger_ptr=nullptr) noexcept
Swaps the contents of this structure and other, or no-op if this == &other.
Basic_blob share_after_split_right(size_type size, log::Logger *logger_ptr=nullptr)
Identical to share_after_split_left(), except this->end() shifts by size to the left (instead of this...
bool zero() const
Returns false if a buffer is allocated and owned; true otherwise.
size_type m_size
See size(); but m_size is meaningless (and containing unknown value) if !buf_ptr() (i....
std::size_t size_type
Type for index into blob or length of blob or sub-blob.
const Allocator & alloc_raw() const
Ref-to-immutable counterpart to the other overload.
Iterator emplace_copy(Const_iterator dest, const boost::asio::const_buffer &src, log::Logger *logger_ptr=nullptr)
Copies src buffer directly onto equally sized area within *this at location dest; *this must have suf...
Allocator & alloc_raw()
For convenience/expressiveness, the allocator object for *this.
std::allocator< uint8_t > Allocator
Short-hand for the allocator type specified at compile-time. Its element type is our value_type.
Basic_blob share_after_split_left(size_type size, log::Logger *logger_ptr=nullptr)
Applicable to !zero() blobs, this shifts this->begin() by size to the right without changing end(); a...
bool derefable_iterator(Const_iterator it) const
Returns true if and only if the given iterator points to an element within this blob's size() element...
const value_type & front() const
Equivalent to const_front().
Iterator end()
Returns pointer one past mutable last element; empty() is possible.
void make_zero(log::Logger *logger_ptr=nullptr)
Guarantees post-condition zero() == true by dropping *this ownership of the allocated internal buffer...
void reserve_impl(size_type capacity, bool clear_on_alloc, log::Logger *logger_ptr)
Implements reserve() overloads.
Const_iterator const_pointer
For container compliance (hence the irregular capitalization): pointer to const element.
static constexpr size_type S_UNCHANGED
Special value indicating an unchanged size_type value; such as in resize().
size_type capacity() const
Returns the number of elements in the internally allocated buffer, which is 1 or more; or 0 if no buf...
void clear()
Equivalent to resize(0, start()).
void swap_impl(Basic_blob &other, log::Logger *logger_ptr) noexcept
The body of swap(), except for the part that swaps (or decides not to swap) alloc_raw().
bool valid_iterator(Const_iterator it) const
Returns true if and only if: this->derefable_iterator(it) || (it == this->const_end()).
static constexpr Flow_log_component S_LOG_COMPONENT
Our flow::log::Component.
Const_iterator const_begin() const
Returns pointer to immutable first element; or end() if empty().
void reserve(size_type capacity, log::Logger *logger_ptr=nullptr)
Ensures that an internal buffer of at least capacity elements is allocated and owned; disallows growi...
boost::asio::const_buffer const_buffer() const
Convenience accessor returning an immutable boost.asio buffer "view" into the entirety of the blob.
void share_after_split_equally_emit_ptr_seq(size_type size, bool headless_pool, Blob_ptr_container *out_blobs, log::Logger *logger_ptr=nullptr)
share_after_split_equally() wrapper that places Ptr<Basic_blob>s into the given container via push_ba...
void resize_impl(size_type size, bool clear_on_alloc, size_type start_or_unchanged, log::Logger *logger_ptr)
Implements resize() overloads.
value_type * data()
Equivalent to begin().
const Buf_ptr & buf_ptr() const
Ref-to-immutable counterpart to the other overload.
Basic_blob & assign(Basic_blob &&moved_src, log::Logger *logger_ptr=nullptr) noexcept
Move assignment.
boost::compressed_pair< Allocator, Buf_ptr > m_alloc_and_buf_ptr
Combined – to enable empty base-class optimization (EBO) – storage for the two data items,...
const value_type & const_front() const
Returns reference to immutable first element.
void share_after_split_equally_impl(size_type size, bool headless_pool, Emit_blob_func &&emit_blob_func, log::Logger *logger_ptr, Share_after_split_left_func &&share_after_split_left_func)
Impl of share_after_split_equally() but capable of emitting not just *this type (Basic_blob<....
Basic_blob(size_type size, Clear_on_alloc coa_tag, log::Logger *logger_ptr=nullptr, const Allocator &alloc_raw_src={})
Identical to similar-sig ctor except, if size > 0, all size elements are performantly initialized to ...
Const_iterator const_iterator
For container compliance (hence the irregular capitalization): Const_iterator type.
void share_after_split_equally_emit_seq(size_type size, bool headless_pool, Blob_container *out_blobs, log::Logger *logger_ptr=nullptr)
share_after_split_equally() wrapper that places Basic_blobs into the given container via push_back().
static constexpr bool S_IS_VANILLA_ALLOC
true if Allocator underlying allocator template is simply std::allocator; false otherwise.
value_type & reference
For container compliance (hence the irregular capitalization): reference to element.
Basic_blob(size_type size, log::Logger *logger_ptr=nullptr, const Allocator &alloc_raw_src={})
Constructs blob with size() and capacity() equal to the given size, and start() == 0.
uint8_t value_type
Short-hand for values, which in this case are unsigned bytes.
value_type * Iterator
Type for iterator pointing into a mutable structure of this type.
Buf_ptr & buf_ptr()
For convenience/expressiveness, the pointer-to-main-buf for *this.
Iterator iterator
For container compliance (hence the irregular capitalization): Iterator type.
static constexpr bool S_SHARING
Value of template parameter SHARING (for generic programming).
Iterator begin()
Returns pointer to mutable first element; or end() if empty().
const value_type & back() const
Equivalent to const_back().
Basic_blob share(log::Logger *logger_ptr=nullptr) const
Applicable to !zero() blobs, this returns an identical Basic_blob that shares (co-owns) *this allocat...
const value_type & const_reference
For container compliance (hence the irregular capitalization): reference to const element.
boost::asio::mutable_buffer mutable_buffer()
Same as const_buffer() but the returned view is mutable.
Iterator erase(Const_iterator first, Const_iterator past_last)
Performs the minimal number of operations to make range [begin(), end()) unchanged except for lacking...
Iterator iterator_sans_const(Const_iterator it)
Returns iterator-to-mutable equivalent to given iterator-to-immutable.
#define FLOW_LOG_TRACE_WITHOUT_CHECKING(ARG_stream_fragment)
Logs a TRACE message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
#define FLOW_LOG_SET_CONTEXT(ARG_logger_ptr, ARG_component_payload)
For the rest of the block within which this macro is instantiated, causes all FLOW_LOG_....
#define FLOW_LOG_TRACE(ARG_stream_fragment)
Logs a TRACE message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
@ S_TRACE
Message indicates any condition that may occur with great frequency (thus verbose if logged).
Flow module containing miscellaneous general-use facilities that don't fit into any other Flow module...
bool in_closed_open_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, given as a [low,...
bool blobs_sharing(const Basic_blob< Allocator_t, SHARING > &blob1, const Basic_blob< Allocator_t, SHARING > &blob2)
Returns true if and only if both given objects are not zero() == true, and they either co-own a commo...
void swap(Basic_blob< Allocator_t, SHARING > &blob1, Basic_blob< Allocator_t, SHARING > &blob2, log::Logger *logger_ptr) noexcept
Equivalent to blob1.swap(blob2).
bool in_closed_range(T const &min_val, T const &val, T const &max_val)
Returns true if and only if the given value is within the given range, inclusive.
Flow_log_component
The flow::log::Component payload enumeration comprising various log components used by Flow's own int...
unsigned char uint8_t
Byte. Best way to represent a byte of binary data. This is 8 bits on all modern systems.
Tag type used at least in Basic_blob and Blob_with_log_context to specify that an allocated buffer be...